├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .mailmap ├── .perltidyrc ├── .travis.yml ├── Changes ├── MANIFEST.SKIP ├── README.pod ├── benchmarks ├── benchmark.pl ├── formfu.pl ├── formfu.yml ├── login-formbuilder.conf ├── login-formfu.yml ├── login.pl └── profile.pl ├── bin ├── html_formfu_deploy.pl └── html_formfu_dumpconf.pl ├── dist.ini ├── examples ├── client-side-constraint │ ├── client-side-constraint.css │ └── client-side-constraint.html ├── unicode │ ├── Changes │ ├── Makefile.PL │ ├── README │ ├── database.sql │ ├── lib │ │ ├── unicode.pm │ │ └── unicode │ │ │ ├── Controller │ │ │ └── Root.pm │ │ │ ├── Model │ │ │ └── DB.pm │ │ │ ├── Schema.pm │ │ │ ├── Schema │ │ │ └── Unicode.pm │ │ │ └── View │ │ │ ├── TT.pm │ │ │ └── TT │ │ │ └── Alloy.pm │ ├── root │ │ ├── favicon.ico │ │ ├── formfu │ │ │ ├── block │ │ │ ├── checkboxgroup │ │ │ ├── checkboxgroup_tag │ │ │ ├── content_button │ │ │ ├── end_block │ │ │ ├── end_form │ │ │ ├── field │ │ │ ├── form │ │ │ ├── input │ │ │ ├── input_tag │ │ │ ├── label │ │ │ ├── multi │ │ │ ├── non_block │ │ │ ├── recaptcha │ │ │ ├── repeatable │ │ │ ├── select_tag │ │ │ ├── start_block │ │ │ ├── start_form │ │ │ └── textarea_tag │ │ ├── forms │ │ │ ├── index.yml │ │ │ ├── view.conf │ │ │ └── view.yml │ │ ├── index.tt │ │ ├── static │ │ │ └── images │ │ │ │ ├── btn_120x50_built.png │ │ │ │ ├── btn_120x50_built_shadow.png │ │ │ │ ├── btn_120x50_powered.png │ │ │ │ ├── btn_120x50_powered_shadow.png │ │ │ │ ├── btn_88x31_built.png │ │ │ │ ├── btn_88x31_built_shadow.png │ │ │ │ ├── btn_88x31_powered.png │ │ │ │ ├── btn_88x31_powered_shadow.png │ │ │ │ └── catalyst_logo.png │ │ ├── vertically-aligned.css │ │ └── view.tt │ ├── script │ │ ├── unicode_cgi.pl │ │ ├── unicode_create.pl │ │ ├── unicode_fastcgi.pl │ │ ├── unicode_server.pl │ │ └── unicode_test.pl │ ├── t │ │ ├── 01app.t │ │ ├── 02pod.t │ │ ├── 03podcoverage.t │ │ ├── model_DB.t │ │ ├── view_TT-Alloy.t │ │ └── view_TT.t │ ├── unicode.db │ └── unicode.yml └── vertically-aligned-css │ ├── test.jpg │ ├── vertically-aligned-ie.css │ ├── vertically-aligned.css │ ├── vertically-aligned.html │ ├── vertically-aligned.pl │ ├── vertically-aligned.tt │ └── vertically-aligned.yml ├── lib └── HTML │ ├── FormFu.pm │ └── FormFu │ ├── Attribute.pm │ ├── Constants.pm │ ├── Constraint.pm │ ├── Constraint │ ├── ASCII.pm │ ├── AllOrNone.pm │ ├── AutoSet.pm │ ├── Bool.pm │ ├── Callback.pm │ ├── CallbackOnce.pm │ ├── DateTime.pm │ ├── DependOn.pm │ ├── Email.pm │ ├── Equal.pm │ ├── File.pm │ ├── File │ │ ├── MIME.pm │ │ ├── MaxSize.pm │ │ ├── MinSize.pm │ │ └── Size.pm │ ├── Integer.pm │ ├── JSON.pm │ ├── Length.pm │ ├── MaxLength.pm │ ├── MaxRange.pm │ ├── MinLength.pm │ ├── MinMaxFields.pm │ ├── MinRange.pm │ ├── Number.pm │ ├── Printable.pm │ ├── Range.pm │ ├── Regex.pm │ ├── Repeatable │ │ └── Any.pm │ ├── Required.pm │ ├── Set.pm │ ├── SingleValue.pm │ └── Word.pm │ ├── Deflator.pm │ ├── Deflator │ ├── Callback.pm │ ├── CompoundDateTime.pm │ ├── CompoundSplit.pm │ ├── FormatNumber.pm │ ├── PathClassFile.pm │ └── Strftime.pm │ ├── Deploy.pm │ ├── Element.pm │ ├── Element │ ├── Blank.pm │ ├── Block.pm │ ├── Button.pm │ ├── Checkbox.pm │ ├── Checkboxgroup.pm │ ├── ComboBox.pm │ ├── ContentButton.pm │ ├── Date.pm │ ├── DateTime.pm │ ├── Email.pm │ ├── Fieldset.pm │ ├── File.pm │ ├── Hidden.pm │ ├── Hr.pm │ ├── Image.pm │ ├── Label.pm │ ├── Multi.pm │ ├── Number.pm │ ├── Password.pm │ ├── Radio.pm │ ├── Radiogroup.pm │ ├── Repeatable.pm │ ├── Reset.pm │ ├── Select.pm │ ├── SimpleTable.pm │ ├── Src.pm │ ├── Submit.pm │ ├── Text.pm │ ├── Textarea.pm │ └── URL.pm │ ├── Exception.pm │ ├── Exception │ ├── Constraint.pm │ ├── Inflator.pm │ ├── Input.pm │ ├── Transformer.pm │ └── Validator.pm │ ├── FakeQuery.pm │ ├── Filter.pm │ ├── Filter │ ├── Callback.pm │ ├── CompoundJoin.pm │ ├── CompoundSprintf.pm │ ├── CopyValue.pm │ ├── Default.pm │ ├── Encode.pm │ ├── ForceListValue.pm │ ├── FormatNumber.pm │ ├── HTMLEscape.pm │ ├── HTMLScrubber.pm │ ├── LowerCase.pm │ ├── NonNumeric.pm │ ├── Regex.pm │ ├── Split.pm │ ├── TrimEdges.pm │ ├── UpperCase.pm │ └── Whitespace.pm │ ├── I18N.pm │ ├── I18N │ ├── bg.pm │ ├── cs.pm │ ├── da.pm │ ├── de.pm │ ├── en.pm │ ├── es.pm │ ├── fr.pm │ ├── hu.pm │ ├── it.pm │ ├── ja.pm │ ├── no.pm │ ├── pt_br.pm │ ├── pt_pt.pm │ ├── ro.pm │ ├── ru.pm │ ├── tr.pm │ ├── ua.pm │ └── zh_cn.pm │ ├── Inflator.pm │ ├── Inflator │ ├── Callback.pm │ ├── CompoundDateTime.pm │ └── DateTime.pm │ ├── Literal.pm │ ├── Localize.pm │ ├── Manual │ ├── Cookbook.pod │ └── Unicode.pod │ ├── Model.pm │ ├── Model │ └── HashRef.pm │ ├── ObjectUtil.pm │ ├── OutputProcessor.pm │ ├── OutputProcessor │ ├── Indent.pm │ └── StripWhitespace.pm │ ├── Plugin.pm │ ├── Plugin │ └── StashValid.pm │ ├── Preload.pm │ ├── Processor.pm │ ├── QueryType │ ├── CGI.pm │ ├── CGI │ │ └── Simple.pm │ └── Catalyst.pm │ ├── Role │ ├── Constraint │ │ └── Others.pm │ ├── ContainsElements.pm │ ├── ContainsElementsSharedWithField.pm │ ├── CreateChildren.pm │ ├── CustomRoles.pm │ ├── Element │ │ ├── Coercible.pm │ │ ├── Field.pm │ │ ├── FieldMethods.pm │ │ ├── Group.pm │ │ ├── Input.pm │ │ ├── Layout.pm │ │ ├── MultiElement.pm │ │ ├── NonBlock.pm │ │ ├── ProcessOptionsFromModel.pm │ │ └── SingleValueField.pm │ ├── Filter │ │ └── Compound.pm │ ├── FormAndBlockMethods.pm │ ├── FormAndElementMethods.pm │ ├── FormBlockAndFieldMethods.pm │ ├── GetProcessors.pm │ ├── HasParent.pm │ ├── NestedHashUtils.pm │ ├── Populate.pm │ └── Render.pm │ ├── Transformer.pm │ ├── Transformer │ └── Callback.pm │ ├── Upload.pm │ ├── UploadParam.pm │ ├── Util.pm │ ├── Validator.pm │ └── Validator │ └── Callback.pm ├── share └── templates │ └── tt │ └── xhtml │ ├── block │ ├── end_block │ ├── end_form │ ├── field │ ├── field_layout │ ├── field_layout_block │ ├── field_layout_checkboxgroup_field │ ├── field_layout_comment │ ├── field_layout_contentbutton_field │ ├── field_layout_errors │ ├── field_layout_field │ ├── field_layout_javascript │ ├── field_layout_label │ ├── field_layout_label_field │ ├── field_layout_label_text │ ├── field_layout_multi_field │ ├── field_layout_parser │ ├── field_layout_select_field │ ├── field_layout_textarea_field │ ├── form │ ├── non_block │ ├── recaptcha │ ├── repeatable │ ├── start_block │ └── start_form ├── t ├── 01use.t ├── 04basic.t ├── 04basic.yml ├── 05_repeated_render.t ├── block_insert_after.t ├── block_insert_before.t ├── bugs │ ├── constructor_arg_overwrites_default.t │ ├── date_element_deflator.t │ ├── date_element_empty_input.t │ ├── datetime_hour_lt_10.t │ ├── disabled_select_default_value.yml │ ├── element_class.t │ ├── element_parent.t │ ├── empty_block_with_nested_name.t │ ├── empty_block_with_nested_name.yml │ ├── error_msg.t │ ├── error_multiple_fields_same_name.t │ ├── error_multiple_fields_same_name.yml │ ├── field_no_name.t │ ├── filter_run_once.t │ ├── multiple_checkbox_same_name.t │ ├── multiple_checkbox_same_name.yml │ ├── name_regex_chars.t │ ├── not_nested.t │ ├── populate_element_coderef.t │ ├── pre_1_00_compat.t │ ├── pre_1_00_compat.yml │ ├── render_processed_value_retain_default.t │ ├── render_processed_value_retain_default.yml │ ├── repeatable_increase_rep.t │ ├── repeatable_increase_rep.yml │ ├── result_params_multiple.t │ ├── select_empty_options.t │ ├── submit_no_value.t │ ├── submit_retain_default.t │ ├── value_empty_string.t │ ├── value_no_default.t │ ├── yaml_utf8.t │ ├── yaml_utf8.txt │ └── yaml_utf8.yml ├── constraints │ ├── allornone.t │ ├── allornone_attach_errors_to_base.t │ ├── allornone_attach_errors_to_base.yml │ ├── allornone_attach_errors_to_others.t │ ├── allornone_attach_errors_to_others.yml │ ├── ascii.t │ ├── autoset.t │ ├── autoset_group.t │ ├── bool.t │ ├── callback.t │ ├── callbackonce.t │ ├── constraint.t │ ├── constraint_other_siblings.t │ ├── constraint_other_siblings.yml │ ├── constraint_other_siblings_not.t │ ├── constraint_other_siblings_not.yml │ ├── constraint_when.t │ ├── constraint_when.yml │ ├── constraint_when_any_field.t │ ├── constraint_when_any_field.yml │ ├── constraint_when_any_true_value.t │ ├── constraint_when_any_true_value.yml │ ├── constraint_when_default_empty_value.t │ ├── constraint_when_default_empty_value.yml │ ├── constraint_when_fields.t │ ├── constraint_when_fields.yml │ ├── datetime_parser.t │ ├── dependon.t │ ├── dependon_attach_errors_to_base.t │ ├── dependon_attach_errors_to_base.yml │ ├── dependon_attach_errors_to_others.t │ ├── dependon_attach_errors_to_others.yml │ ├── email-mx.t │ ├── email.t │ ├── equal.t │ ├── equal_internals.t │ ├── equal_not.t │ ├── file.t │ ├── file.yml │ ├── file_maxsize.t │ ├── file_maxsize.yml │ ├── file_mime.t │ ├── file_mime.yml │ ├── file_minsize.t │ ├── file_minsize.yml │ ├── file_size.t │ ├── file_size.yml │ ├── integer.t │ ├── json.t │ ├── length.t │ ├── localize.t │ ├── maxlength.t │ ├── maxrange.t │ ├── minlength.t │ ├── minmaxfields.t │ ├── minmaxfields_with_filter_split.t │ ├── minmaxfields_with_filter_split.yml │ ├── minrange.t │ ├── not_equal.t │ ├── not_word.t │ ├── number.t │ ├── printable.t │ ├── range.t │ ├── regex.t │ ├── regex_anchored.t │ ├── regex_common.t │ ├── repeatable_any.t │ ├── repeatable_any.yml │ ├── repeatable_any_not_increment_field_n.t │ ├── repeatable_any_not_increment_field_n.yml │ ├── required.t │ ├── required_file.t │ ├── required_file.yml │ ├── required_only_on_reps.t │ ├── required_only_on_reps.yml │ ├── set.t │ ├── singlevalue.t │ ├── word.t │ └── xml.t ├── deflators │ ├── callback.t │ ├── compounddatetime.t │ ├── compounddatetime.yml │ ├── compounddatetime_field_order.t │ ├── compounddatetime_field_order.yml │ ├── compoundsplit.t │ ├── compoundsplit.yml │ ├── compoundsplit_after_submit.t │ ├── compoundsplit_after_submit.yml │ ├── compoundsplit_field_order.t │ ├── compoundsplit_field_order.yml │ ├── compoundsplit_split.t │ ├── compoundsplit_split.yml │ ├── formatnumber.t │ ├── formatnumber.yml │ └── pathclassfile.t ├── elements-file_post.t ├── elements-file_post.txt ├── elements │ ├── blank.t │ ├── block.t │ ├── block_auto_block_id.t │ ├── block_auto_block_id.yml │ ├── block_repeatable.t │ ├── block_repeatable.yml │ ├── block_repeatable_attrs.t │ ├── block_repeatable_attrs.yml │ ├── block_repeatable_auto_block_id.t │ ├── block_repeatable_auto_block_id.yml │ ├── block_repeatable_auto_id.t │ ├── block_repeatable_auto_id.yml │ ├── block_repeatable_date.t │ ├── block_repeatable_date.yml │ ├── block_repeatable_inc.t │ ├── block_repeatable_inc.yml │ ├── block_repeatable_multi.t │ ├── block_repeatable_tag.t │ ├── block_repeatable_tag.yml │ ├── button.t │ ├── button_no_name.t │ ├── checkbox.t │ ├── checkbox_force_default.t │ ├── checkbox_retain_default.t │ ├── checkbox_reverse.t │ ├── checkbox_reverse.yml │ ├── checkboxgroup.t │ ├── checkboxgroup_attributes_escaped.t │ ├── checkboxgroup_attributes_escaped.yml │ ├── combobox.t │ ├── combobox.yml │ ├── combobox_repeatable.t │ ├── combobox_repeatable.yml │ ├── combobox_required.t │ ├── combobox_required.yml │ ├── content_button.t │ ├── date.t │ ├── date_default.t │ ├── date_default_datetime_args.t │ ├── date_default_datetime_args.yml │ ├── date_default_empty.t │ ├── date_month_year.t │ ├── date_natural.t │ ├── date_order.t │ ├── date_order_error.t │ ├── date_rename.t │ ├── date_undef.t │ ├── date_year_reverse.t │ ├── date_year_reverse.yml │ ├── datetime.t │ ├── datetime.yml │ ├── datetime_interval.t │ ├── datetime_interval.yml │ ├── datetime_seconds.t │ ├── datetime_seconds.yml │ ├── element_setup.t │ ├── email.t │ ├── error_attributes_failing_test.select-with-attrs.yml │ ├── error_attributes_failing_test.select.yml │ ├── error_attributes_failing_test.t │ ├── error_attributes_failing_test.text-with-attrs.yml │ ├── error_attributes_failing_test.text.yml │ ├── escaping.t │ ├── field_default_empty_value.t │ ├── field_default_empty_value.yml │ ├── field_non_param.t │ ├── fieldset.t │ ├── fieldset_legend_attrs.t │ ├── fieldset_legend_attrs.yml │ ├── file.t │ ├── file_post.txt │ ├── file_post_cgi_simple.t │ ├── hidden.t │ ├── hr.t │ ├── image.t │ ├── label.t │ ├── label.yml │ ├── label_value_submission.t │ ├── label_value_submission.yml │ ├── multi.t │ ├── multi_errors.t │ ├── multiple_submit_buttons.t │ ├── no_block_tag.t │ ├── no_block_tag.yml │ ├── no_container_tag.t │ ├── no_container_tag.yml │ ├── number.t │ ├── number.yml │ ├── object.t │ ├── object │ │ └── field_layout_field_custom │ ├── password.t │ ├── password_render_value.t │ ├── password_retain_default.t │ ├── radio.t │ ├── radio_force_default.t │ ├── radio_retain_default.t │ ├── radiogroup.t │ ├── radiogroup_attributes_escaped.t │ ├── radiogroup_attributes_escaped.yml │ ├── radiogroup_attrs_xml.t │ ├── radiogroup_dup_opt.t │ ├── radiogroup_errors.t │ ├── radiogroup_force_default.t │ ├── radiogroup_id.t │ ├── radiogroup_id_value.t │ ├── radiogroup_retain_default.t │ ├── radiogroup_subgroup.t │ ├── radiogroup_unknown_opt.t │ ├── radiogroup_xml.t │ ├── render_method.t │ ├── repeatable_counter_name.t │ ├── repeatable_counter_name.yml │ ├── repeatable_repeatable.t │ ├── repeatable_repeatable.yml │ ├── reset.t │ ├── reverse.t │ ├── select.t │ ├── select_attributes_escaped.t │ ├── select_attributes_escaped.yml │ ├── select_deflator_default.t │ ├── select_empty_first.t │ ├── select_empty_first.yml │ ├── select_empty_first_label.t │ ├── select_force_default.t │ ├── select_label_loc.t │ ├── select_multi_default_values.t │ ├── select_multi_value.t │ ├── select_optgroup.t │ ├── select_options.t │ ├── select_retain_default.t │ ├── select_same_name.t │ ├── select_same_name.yml │ ├── select_value_range.t │ ├── simple_table.t │ ├── simple_table.yml │ ├── simple_table_class.t │ ├── simple_table_class.yml │ ├── simple_table_multiple.t │ ├── simple_table_multiple.yml │ ├── src.t │ ├── submit.t │ ├── text.t │ ├── text_attributes.t │ ├── text_auto_comment_class.t │ ├── text_auto_comment_class.yml │ ├── text_auto_container_class.t │ ├── text_auto_container_class.yml │ ├── text_auto_container_comment_class.t │ ├── text_auto_container_comment_class.yml │ ├── text_auto_container_error_class.t │ ├── text_auto_container_error_class.yml │ ├── text_auto_container_label_class.t │ ├── text_auto_container_label_class.yml │ ├── text_auto_label_class.t │ ├── text_auto_label_class.yml │ ├── text_datalist_options.t │ ├── text_datalist_options.yml │ ├── text_datalist_values.t │ ├── text_datalist_values.yml │ ├── text_errors.t │ ├── text_force_default.t │ ├── text_layout.t │ ├── text_layout.yml │ ├── text_retain_default.t │ ├── text_title.t │ ├── textarea.t │ ├── url.t │ └── url.yml ├── examples │ ├── custom_label.t │ ├── custom_label2.t │ ├── field_as.t │ └── fields_as_list_items.t ├── field_accessor_loc.t ├── field_accessor_loc_arrayref.t ├── field_accessor_loc_arrayref.yml ├── field_change_name.t ├── field_id.t ├── filters │ ├── all_by_default.t │ ├── callback.t │ ├── compoundjoin.t │ ├── compoundjoin.yml │ ├── compoundjoin_field_order.t │ ├── compoundjoin_field_order.yml │ ├── compoundjoin_join.t │ ├── compoundjoin_join.yml │ ├── compoundsprintf.t │ ├── compoundsprintf.yml │ ├── compoundsprintf_field_order.t │ ├── compoundsprintf_field_order.yml │ ├── copyvalue.t │ ├── encode.t │ ├── filter.t │ ├── formatnumber.t │ ├── formatnumber.yml │ ├── htmlescape.t │ ├── htmlscrubber.t │ ├── lowercase.t │ ├── nonnumeric.t │ ├── regex.t │ ├── regex.yml │ ├── regex_eval.t │ ├── regex_eval.yml │ ├── split.t │ ├── split.yml │ ├── trimedges.t │ ├── uppercase.t │ └── whitespace.t ├── force_errors │ ├── allornone.t │ ├── callbackonce.t │ ├── dependon.t │ ├── equal.t │ ├── force_errors.t │ ├── integer.t │ └── minmaxfields.t ├── form │ ├── add_render_class_args.t │ ├── add_valid.t │ ├── add_valid_unknown.t │ ├── attributes.t │ ├── auto_constraint_class.t │ ├── auto_error_class.t │ ├── auto_error_field_class.t │ ├── auto_error_message.t │ ├── auto_fieldset.t │ ├── auto_label.t │ ├── clone.t │ ├── config_callback.t │ ├── config_callback.yml │ ├── constraints_from_dbic.t │ ├── constraints_from_dbic.yml │ ├── constraints_from_dbic_rs.t │ ├── default_args.t │ ├── default_args_alt.t │ ├── default_args_alt.yml │ ├── default_args_isa.t │ ├── default_args_isa.yml │ ├── default_args_not_inheriting.t │ ├── default_values.t │ ├── end.t │ ├── error_message.t │ ├── force_error_message.t │ ├── form_error_message_class.t │ ├── get_all_elements.t │ ├── get_constraint.t │ ├── get_constraints.t │ ├── get_deflator.t │ ├── get_deflators.t │ ├── get_element.t │ ├── get_elements.t │ ├── get_errors.t │ ├── get_field.t │ ├── get_fields.t │ ├── get_filter.t │ ├── get_filters.t │ ├── get_inflator.t │ ├── get_inflators.t │ ├── get_parent.t │ ├── get_parent.yml │ ├── has_errors.t │ ├── hidden_fields.t │ ├── init_arg.t │ ├── insert_after.t │ ├── insert_before.t │ ├── javascript.t │ ├── javascript_src.t │ ├── languages.t │ ├── languages.yml │ ├── model.t │ ├── multiple_same_named_fields.t │ ├── object.t │ ├── object │ │ └── form │ ├── param.t │ ├── param_array.t │ ├── param_list.t │ ├── param_value.t │ ├── params.t │ ├── params_ignore_underscore.t │ ├── query.t │ ├── render_processed_value.t │ ├── render_processed_value.yml │ ├── start.t │ ├── stash.t │ ├── submitted.t │ ├── submitted_and_valid.t │ ├── title_xml.t │ └── valid.t ├── i18n │ ├── add_localize_object.t │ ├── add_localize_object_from_class.t │ └── add_localize_object_from_class.yml ├── inflators │ ├── array.t │ ├── callback.t │ ├── compounddatetime.t │ ├── compounddatetime.yml │ ├── compounddatetime_field_order.t │ ├── compounddatetime_field_order.yml │ ├── datetime_optional.t │ ├── datetime_parser.t │ ├── datetime_regex.t │ ├── datetime_regex_string.t │ ├── datetime_strptime.t │ ├── datetime_timezone.t │ ├── datetime_with_constraint.t │ └── datetime_with_constraint.yml ├── internals │ ├── default_args-types.t │ └── default_args-types.yml ├── lib │ ├── HTMLFormFu │ │ ├── DBICUniqueFake.pm │ │ ├── ElementSetup.pm │ │ ├── I18N.pm │ │ ├── I18N │ │ │ └── en.pm │ │ ├── MyBlockRole.pm │ │ ├── MyDeflator.pm │ │ ├── MyFieldRole.pm │ │ ├── MyFormRole.pm │ │ ├── MyModel.pm │ │ ├── MyObject.pm │ │ ├── MyValidator.pm │ │ ├── RegressLocalization.pm │ │ ├── RegressLocalization │ │ │ └── en.pm │ │ └── TestLib.pm │ └── MyApp │ │ ├── Schema.pm │ │ └── Schema │ │ ├── Dongle.pm │ │ └── Person.pm ├── load_config │ ├── config_file_path.t │ ├── config_file_path │ │ └── form.yml │ ├── config_file_path2 │ │ └── form.yml │ ├── load_config_file.t │ ├── load_config_file_constraint_regex.t │ ├── load_config_file_constraint_regex.yml │ ├── load_config_file_fieldset.yml │ ├── load_config_file_form.yml │ ├── load_config_file_multi_stream.t │ ├── load_config_file_multi_stream.yml │ ├── load_config_file_multiple.t │ ├── load_config_file_multiple.yml │ ├── load_config_file_multiple1.yml │ ├── load_config_file_multiple2.yml │ └── load_config_filestem.t ├── model │ ├── hashref_create.t │ ├── hashref_create_repeatable_without_nn.t │ ├── hashref_create_repeatable_without_nn.yml │ ├── hashref_default_values.t │ ├── hashref_escaping.t │ ├── hashref_multi_within_rep.t │ ├── hashref_multi_within_rep.yml │ └── hashref_process.t ├── multiple_select_fields.t ├── multiple_text_fields.t ├── nested-elements-file_post.t ├── nested │ ├── constraints │ │ ├── allornone.t │ │ ├── callbackonce.t │ │ ├── constraint_when.t │ │ ├── constraint_when.yml │ │ ├── dependon.t │ │ ├── equal.t │ │ ├── minmaxfields.t │ │ └── required.t │ ├── element_name.t │ ├── element_name.yml │ ├── elements │ │ ├── block_repeatable_multi_named.t │ │ ├── block_repeatable_multi_named.yml │ │ ├── block_repeatable_multi_named_filter.t │ │ ├── block_repeatable_multi_named_filter.yml │ │ ├── block_without_name.t │ │ ├── block_without_name.yml │ │ ├── checkbox_force_default.t │ │ ├── checkbox_retain_default.t │ │ ├── combobox.t │ │ ├── date.t │ │ ├── multi.t │ │ ├── multi_named.t │ │ ├── radio.t │ │ ├── radio_force_default.t │ │ ├── radio_retain_default.t │ │ ├── radiogroup.t │ │ ├── radiogroup_force_default.t │ │ ├── radiogroup_retain_default.t │ │ ├── repeatable_repeatable.t │ │ ├── repeatable_repeatable.yml │ │ ├── select.t │ │ ├── select_force_default.t │ │ ├── select_retain_default.t │ │ ├── select_same_name.t │ │ ├── select_same_name.yml │ │ └── text.t │ ├── filters │ │ └── regex.t │ ├── form │ │ ├── render_processed_value.t │ │ └── render_processed_value.yml │ ├── form_input.t │ ├── illegal_name.t │ ├── inflators │ │ └── datetime_strptime.t │ ├── internals │ │ ├── form_processed_params.t │ │ └── hash_keys.t │ ├── param.t │ ├── params.t │ ├── pre_expanded.t │ ├── transformers │ │ └── callback.t │ ├── valid.t │ └── validators │ │ └── callback.t ├── output_processors │ ├── indent.t │ ├── indent_internals.t │ ├── strip_whitespace.t │ └── strip_whitespace.yml ├── plugins │ ├── stashvalid.t │ ├── stashvalid.yml │ ├── stashvalid_on_field.t │ └── stashvalid_on_field.yml ├── repeatable │ ├── clone.t │ ├── clone.yml │ ├── constraints │ │ ├── attach_errors_to.t │ │ ├── attach_errors_to.yml │ │ ├── equal.t │ │ ├── equal.yml │ │ ├── required.t │ │ ├── required.yml │ │ ├── required_not_increment_field_names.t │ │ ├── required_not_increment_field_names.yml │ │ ├── required_not_nested.t │ │ ├── required_not_nested.yml │ │ ├── when.t │ │ └── when.yml │ └── repeatable │ │ └── constraints │ │ ├── repeatable_any.t │ │ └── repeatable_any.yml ├── roles │ ├── block.t │ ├── block.yml │ ├── field.t │ ├── field.yml │ ├── form.t │ └── form.yml ├── templates │ └── field_layout ├── transformers │ └── callback.t ├── utils │ ├── append_xml_attribute.t │ ├── has_xml_attribute.t │ └── remove_xml_attribute.t └── validators │ ├── callback.t │ └── validator.t └── xt ├── circular_reference.t └── circular_reference.yml /.gitignore: -------------------------------------------------------------------------------- 1 | *.tar.gz 2 | .build 3 | .DS_Store 4 | blib/ 5 | HTML-FormFu-* 6 | inc/ 7 | Makefile 8 | Makefile.old 9 | Makefile.old 10 | MANIFEST 11 | META.json 12 | META.yml 13 | MYMETA.json 14 | MYMETA.yml 15 | pm_to_blib 16 | README 17 | -------------------------------------------------------------------------------- /.mailmap: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | <1nd@gmx.de> 6 | 7 | 8 | -------------------------------------------------------------------------------- /.perltidyrc: -------------------------------------------------------------------------------- 1 | -l=80 # Max line width 2 | -i=4 # Indent level is 4 cols 3 | -ci=4 # Continuation indent is 4 cols 4 | # -st # Output to STDOUT 5 | -se # Errors to STDERR 6 | -vt=2 # Maximal vertical tightness 7 | -cti=0 # No extra indentation for closing brackets 8 | -pt=1 # Medium parenthesis tightness 9 | -bt=1 # Medium brace tightness 10 | -sbt=1 # Medium square bracket tightness 11 | -bbt=1 # Medium block brace tightness 12 | -nsfs # No space before semicolons 13 | -nolq # Don't outdent long quoted strings 14 | -wbb="% + - * / x != == >= <= =~ !~ < > | & >= < = **= += *= &= <<= &&= -= /= |= >>= ||= .= %= ^= x=" 15 | # Break before all operators 16 | -sot # Stack opening tokens 17 | -sct # Stack closing tokens 18 | -------------------------------------------------------------------------------- /MANIFEST.SKIP: -------------------------------------------------------------------------------- 1 | # Don't know if it's getting kept 2 | ^lib\/HTML\/FormFu\/Filter\/Default\.pm$ 3 | 4 | # not ready yet 5 | ^t\/multiform-misc\/file 6 | 7 | ^benchmarks\b 8 | ^examples\/client-side-constraint\b 9 | 10 | ^\.perltidyrc$ 11 | -------------------------------------------------------------------------------- /benchmarks/login-formbuilder.conf: -------------------------------------------------------------------------------- 1 | method: POST 2 | 3 | fields: 4 | username: 5 | size: 10 6 | label: Username 7 | required: 1 8 | 9 | password: 10 | size: 10 11 | label: Password 12 | required: 1 13 | 14 | -------------------------------------------------------------------------------- /benchmarks/login-formfu.yml: -------------------------------------------------------------------------------- 1 | --- 2 | #tt_args: 3 | # TEMPLATE_ALLOY: 1 4 | # COMPILE_DIR: 'benchmarks/cache' 5 | # COMPILE_PERL: 1 6 | # INCLUDE_PATH: 'share/templates/tt/xhtml' 7 | 8 | render_method: string 9 | 10 | auto_fieldset: 1 11 | 12 | elements: 13 | - type: Text 14 | name: username 15 | size: 10 16 | label: Username 17 | constraints: 18 | - type: Required 19 | 20 | - type: Password 21 | name: password 22 | size: 10 23 | label: Password 24 | constraints: 25 | - type: Required 26 | 27 | - type: Submit 28 | name: _submit 29 | 30 | indicator: username 31 | -------------------------------------------------------------------------------- /examples/unicode/Changes: -------------------------------------------------------------------------------- 1 | This file documents the revision history for Perl extension unicode. 2 | 3 | 0.01 2007-10-15 11:48:29 4 | - initial revision, generated by Catalyst 5 | -------------------------------------------------------------------------------- /examples/unicode/Makefile.PL: -------------------------------------------------------------------------------- 1 | use inc::Module::Install; 2 | 3 | name 'unicode'; 4 | all_from 'lib/unicode.pm'; 5 | 6 | requires 'Catalyst' => '5.7008'; 7 | requires 'Catalyst::Plugin::ConfigLoader'; 8 | requires 'Catalyst::Plugin::Static::Simple'; 9 | requires 'Catalyst::Plugin::Unicode'; 10 | requires 'Catalyst::Controller::HTML::FormFu'; 11 | requires 'Catalyst::Action::RenderView'; 12 | requires 'Catalyst::View::TT'; 13 | requires 'Catalyst::View::TT::Alloy'; 14 | requires 'Config::General'; 15 | requires 'DBIx::Class::Schema'; 16 | requires 'HTML::FormFu'; 17 | requires 'HTML::FormFu::Model::DBIC'; 18 | requires 'YAML::XS'; 19 | 20 | catalyst; 21 | 22 | install_script glob('script/*.pl'); 23 | auto_install; 24 | WriteAll; 25 | -------------------------------------------------------------------------------- /examples/unicode/README: -------------------------------------------------------------------------------- 1 | Run `perl Makefile.PL` to check you've got all dependencies installed. 2 | 3 | Run `perl script/unicode_server.pl` to start the application. 4 | 5 | View the site in your web-browser. 6 | -------------------------------------------------------------------------------- /examples/unicode/database.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `unicode` ( 2 | `id` INTEGER PRIMARY KEY NOT NULL, 3 | `string` VARCHAR(255) 4 | ); 5 | 6 | INSERT INTO `unicode` (`id`, `string`) VALUES (1, 'Ungültig'); 7 | -------------------------------------------------------------------------------- /examples/unicode/lib/unicode/Model/DB.pm: -------------------------------------------------------------------------------- 1 | package unicode::Model::DB; 2 | 3 | use strict; 4 | use base 'Catalyst::Model::DBIC::Schema'; 5 | 6 | __PACKAGE__->config( 7 | schema_class => 'unicode::Schema', 8 | connect_info => [ 9 | 'dbi:SQLite:dbname=unicode.db', 10 | 11 | ], 12 | 13 | ); 14 | 15 | =head1 NAME 16 | 17 | unicode::Model::DB - Catalyst DBIC Schema Model 18 | =head1 SYNOPSIS 19 | 20 | See L 21 | 22 | =head1 DESCRIPTION 23 | 24 | L Model using schema L 25 | 26 | =head1 AUTHOR 27 | 28 | Carl Franks 29 | 30 | =head1 LICENSE 31 | 32 | This library is free software, you can redistribute it and/or modify 33 | it under the same terms as Perl itself. 34 | 35 | =cut 36 | 37 | 1; 38 | -------------------------------------------------------------------------------- /examples/unicode/lib/unicode/Schema.pm: -------------------------------------------------------------------------------- 1 | package unicode::Schema; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use base 'DBIx::Class::Schema'; 7 | 8 | __PACKAGE__->load_classes; 9 | 10 | 1; 11 | 12 | -------------------------------------------------------------------------------- /examples/unicode/lib/unicode/Schema/Unicode.pm: -------------------------------------------------------------------------------- 1 | package unicode::Schema::Unicode; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use base 'DBIx::Class'; 7 | 8 | __PACKAGE__->load_components(qw/ UTF8Columns PK::Auto Core /); 9 | 10 | __PACKAGE__->table("unicode"); 11 | 12 | __PACKAGE__->add_columns( 13 | "id", 14 | { 15 | data_type => "INTEGER", 16 | is_nullable => 0, 17 | }, 18 | "string", 19 | { data_type => "VARCHAR", 20 | size => 255 21 | }, 22 | ); 23 | 24 | __PACKAGE__->utf8_columns(qw/ string /); 25 | 26 | __PACKAGE__->set_primary_key("id"); 27 | 28 | 1; 29 | -------------------------------------------------------------------------------- /examples/unicode/lib/unicode/View/TT.pm: -------------------------------------------------------------------------------- 1 | package unicode::View::TT; 2 | 3 | use strict; 4 | use base 'Catalyst::View::TT'; 5 | 6 | __PACKAGE__->config(TEMPLATE_EXTENSION => '.tt'); 7 | 8 | =head1 NAME 9 | 10 | unicode::View::TT - TT View for unicode 11 | 12 | =head1 DESCRIPTION 13 | 14 | TT View for unicode. 15 | 16 | =head1 AUTHOR 17 | 18 | =head1 SEE ALSO 19 | 20 | L 21 | 22 | Carl Franks 23 | 24 | =head1 LICENSE 25 | 26 | This library is free software, you can redistribute it and/or modify 27 | it under the same terms as Perl itself. 28 | 29 | =cut 30 | 31 | 1; 32 | -------------------------------------------------------------------------------- /examples/unicode/lib/unicode/View/TT/Alloy.pm: -------------------------------------------------------------------------------- 1 | package unicode::View::TT::Alloy; 2 | 3 | use strict; 4 | use base 'Catalyst::View::TT::Alloy'; 5 | 6 | 1; 7 | 8 | -------------------------------------------------------------------------------- /examples/unicode/root/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FormFu/HTML-FormFu/17eb6f1fb450dbd339efed9e4f6b6d53a5d35638/examples/unicode/root/favicon.ico -------------------------------------------------------------------------------- /examples/unicode/root/formfu/block: -------------------------------------------------------------------------------- 1 | [% INCLUDE start_block %] 2 | [% IF self.content.defined %][% self.content %] 3 | [% ELSE %][% FOREACH element = self.elements %][% INCLUDE $element.filename self = element %] 4 | [% END %][% END %][% INCLUDE end_block %] -------------------------------------------------------------------------------- /examples/unicode/root/formfu/checkboxgroup: -------------------------------------------------------------------------------- 1 | [% WRAPPER field %][% INCLUDE $self.checkboxgroup_filename %][% END %] -------------------------------------------------------------------------------- /examples/unicode/root/formfu/checkboxgroup_tag: -------------------------------------------------------------------------------- 1 | 2 | [% FOREACH option = self.options %][% IF option.group %] 3 | [% FOREACH item = option.group %] 4 | 5 | [% item.label %] 6 | 7 | [% END %] 8 | [% ELSE %] 9 | 10 | [% option.label %] 11 | 12 | [% END %][% END %] -------------------------------------------------------------------------------- /examples/unicode/root/formfu/content_button: -------------------------------------------------------------------------------- 1 | [% WRAPPER field %][% END %] -------------------------------------------------------------------------------- /examples/unicode/root/formfu/end_block: -------------------------------------------------------------------------------- 1 | [% IF self.tag.defined %][% END %] -------------------------------------------------------------------------------- /examples/unicode/root/formfu/end_form: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/unicode/root/formfu/form: -------------------------------------------------------------------------------- 1 | [% INCLUDE start_form %] 2 | [% FOREACH element = self.elements %][% INCLUDE $element.filename self=element %] 3 | [% END %][% INCLUDE end_form %] 4 | -------------------------------------------------------------------------------- /examples/unicode/root/formfu/input: -------------------------------------------------------------------------------- 1 | [% WRAPPER field %][% INCLUDE $self.field_filename %][% END %] -------------------------------------------------------------------------------- /examples/unicode/root/formfu/input_tag: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/unicode/root/formfu/label: -------------------------------------------------------------------------------- 1 | <[% self.label_tag %][% process_attrs(self.label_attributes) %]>[% self.label %] -------------------------------------------------------------------------------- /examples/unicode/root/formfu/multi: -------------------------------------------------------------------------------- 1 | [% WRAPPER field %] 2 | [% FOREACH element = self.elements %][% IF element.reverse_multi %][% INCLUDE $element.field_filename self = element %][% IF element.label.defined %] 3 | [% INCLUDE $element.label_filename self = element %][% END %][% ELSE %][% IF element.label.defined %][% INCLUDE $element.label_filename self = element %] 4 | [% END %][% INCLUDE $element.field_filename self = element %][% END %] 5 | [% END %][% END %] -------------------------------------------------------------------------------- /examples/unicode/root/formfu/non_block: -------------------------------------------------------------------------------- 1 | <[% self.tag %][% process_attrs(self.attributes) %] /> -------------------------------------------------------------------------------- /examples/unicode/root/formfu/recaptcha: -------------------------------------------------------------------------------- 1 | [% WRAPPER field %] 2 | [% self.recaptcha_html %][% END %] -------------------------------------------------------------------------------- /examples/unicode/root/formfu/repeatable: -------------------------------------------------------------------------------- 1 | [% FOREACH element = self.elements %][% INCLUDE $element.filename self = element %][% UNLESS loop.last %] 2 | [% END %][% END %] -------------------------------------------------------------------------------- /examples/unicode/root/formfu/select_tag: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/unicode/root/formfu/start_block: -------------------------------------------------------------------------------- 1 | [% IF self.tag.defined %]<[% self.tag %][% process_attrs(self.attributes) %]>[% END %][% IF self.legend.defined %] 2 | [% self.legend %][% END %] -------------------------------------------------------------------------------- /examples/unicode/root/formfu/start_form: -------------------------------------------------------------------------------- 1 | [% IF self.form_error_message.defined %] 2 |
[% self.form_error_message %]
[% END %][% IF self.javascript_src.defined %][% FOREACH src = self.javascript_src.list %] 3 | [% END %][% END %][% IF self.javascript.defined %] 5 | [% END %] -------------------------------------------------------------------------------- /examples/unicode/root/formfu/textarea_tag: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/unicode/root/forms/view.conf: -------------------------------------------------------------------------------- 1 | 2 | legend Demo Form 3 | 4 | 5 | languages de 6 | 7 | 8 | type Text 9 | name yml 10 | label From the form config -> 11 | default ü 12 | 13 | 14 | 15 | type Text 16 | name db 17 | label From the database -> 18 | 19 | 20 | 21 | type Date 22 | name date 23 | label From DateTime::Locale -> 24 | 25 | 26 | 27 | type Submit 28 | name submit 29 | 30 | -------------------------------------------------------------------------------- /examples/unicode/root/forms/view.yml: -------------------------------------------------------------------------------- 1 | auto_fieldset: 2 | legend: Demo Form 3 | 4 | languages: [de] 5 | 6 | elements: 7 | - type: Text 8 | name: yml 9 | label: 'From the form config ->' 10 | default: 'ü' 11 | 12 | - type: Text 13 | name: db 14 | label: 'From the database ->' 15 | 16 | - type: Date 17 | name: date 18 | label: 'From DateTime::Locale ->' 19 | 20 | - type: Submit 21 | name: submit 22 | -------------------------------------------------------------------------------- /examples/unicode/root/index.tt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | [% form %] 9 | 10 | -------------------------------------------------------------------------------- /examples/unicode/root/static/images/btn_120x50_built.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FormFu/HTML-FormFu/17eb6f1fb450dbd339efed9e4f6b6d53a5d35638/examples/unicode/root/static/images/btn_120x50_built.png -------------------------------------------------------------------------------- /examples/unicode/root/static/images/btn_120x50_built_shadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FormFu/HTML-FormFu/17eb6f1fb450dbd339efed9e4f6b6d53a5d35638/examples/unicode/root/static/images/btn_120x50_built_shadow.png -------------------------------------------------------------------------------- /examples/unicode/root/static/images/btn_120x50_powered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FormFu/HTML-FormFu/17eb6f1fb450dbd339efed9e4f6b6d53a5d35638/examples/unicode/root/static/images/btn_120x50_powered.png -------------------------------------------------------------------------------- /examples/unicode/root/static/images/btn_120x50_powered_shadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FormFu/HTML-FormFu/17eb6f1fb450dbd339efed9e4f6b6d53a5d35638/examples/unicode/root/static/images/btn_120x50_powered_shadow.png -------------------------------------------------------------------------------- /examples/unicode/root/static/images/btn_88x31_built.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FormFu/HTML-FormFu/17eb6f1fb450dbd339efed9e4f6b6d53a5d35638/examples/unicode/root/static/images/btn_88x31_built.png -------------------------------------------------------------------------------- /examples/unicode/root/static/images/btn_88x31_built_shadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FormFu/HTML-FormFu/17eb6f1fb450dbd339efed9e4f6b6d53a5d35638/examples/unicode/root/static/images/btn_88x31_built_shadow.png -------------------------------------------------------------------------------- /examples/unicode/root/static/images/btn_88x31_powered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FormFu/HTML-FormFu/17eb6f1fb450dbd339efed9e4f6b6d53a5d35638/examples/unicode/root/static/images/btn_88x31_powered.png -------------------------------------------------------------------------------- /examples/unicode/root/static/images/btn_88x31_powered_shadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FormFu/HTML-FormFu/17eb6f1fb450dbd339efed9e4f6b6d53a5d35638/examples/unicode/root/static/images/btn_88x31_powered_shadow.png -------------------------------------------------------------------------------- /examples/unicode/root/static/images/catalyst_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FormFu/HTML-FormFu/17eb6f1fb450dbd339efed9e4f6b6d53a5d35638/examples/unicode/root/static/images/catalyst_logo.png -------------------------------------------------------------------------------- /examples/unicode/root/view.tt: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | Unicode Demo 7 | 8 | 11 | 12 | 13 |

home

14 | [% form %] 15 |

UTF8 in the template file -> ü

16 |

UTF8 from the database -> [% c.model('DB').resultset('Unicode').find(1).string %]

17 | [% demo_form %] 18 | 19 | 20 | -------------------------------------------------------------------------------- /examples/unicode/script/unicode_cgi.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | BEGIN { $ENV{CATALYST_ENGINE} ||= 'CGI' } 4 | 5 | use strict; 6 | use warnings; 7 | use FindBin; 8 | use lib "$FindBin::Bin/../lib"; 9 | use unicode; 10 | 11 | unicode->run; 12 | 13 | 1; 14 | 15 | =head1 NAME 16 | 17 | unicode_cgi.pl - Catalyst CGI 18 | 19 | =head1 SYNOPSIS 20 | 21 | See L 22 | 23 | =head1 DESCRIPTION 24 | 25 | Run a Catalyst application as a cgi script. 26 | 27 | =head1 AUTHORS 28 | 29 | Catalyst Contributors, see Catalyst.pm 30 | 31 | =head1 COPYRIGHT 32 | 33 | 34 | This library is free software, you can redistribute it and/or modify 35 | it under the same terms as Perl itself. 36 | 37 | =cut 38 | -------------------------------------------------------------------------------- /examples/unicode/t/01app.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use Test::More tests => 2; 4 | 5 | BEGIN { use_ok 'Catalyst::Test', 'unicode' } 6 | 7 | ok( request('/')->is_success, 'Request should succeed' ); 8 | -------------------------------------------------------------------------------- /examples/unicode/t/02pod.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use Test::More; 4 | 5 | eval "use Test::Pod 1.14"; 6 | plan skip_all => 'Test::Pod 1.14 required' if $@; 7 | plan skip_all => 'set TEST_POD to enable this test' unless $ENV{TEST_POD}; 8 | 9 | all_pod_files_ok(); 10 | -------------------------------------------------------------------------------- /examples/unicode/t/03podcoverage.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use Test::More; 4 | 5 | eval "use Test::Pod::Coverage 1.04"; 6 | plan skip_all => 'Test::Pod::Coverage 1.04 required' if $@; 7 | plan skip_all => 'set TEST_POD to enable this test' unless $ENV{TEST_POD}; 8 | 9 | all_pod_coverage_ok(); 10 | -------------------------------------------------------------------------------- /examples/unicode/t/model_DB.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use Test::More tests => 1; 4 | 5 | BEGIN { use_ok 'unicode::Model::DB' } 6 | 7 | -------------------------------------------------------------------------------- /examples/unicode/t/view_TT-Alloy.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use Test::More tests => 1; 4 | 5 | BEGIN { use_ok 'unicode::View::TT::Alloy' } 6 | 7 | -------------------------------------------------------------------------------- /examples/unicode/t/view_TT.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use Test::More tests => 1; 4 | 5 | BEGIN { use_ok 'unicode::View::TT' } 6 | 7 | -------------------------------------------------------------------------------- /examples/unicode/unicode.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FormFu/HTML-FormFu/17eb6f1fb450dbd339efed9e4f6b6d53a5d35638/examples/unicode/unicode.db -------------------------------------------------------------------------------- /examples/unicode/unicode.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: unicode 3 | 4 | 'Controller::HTML::FormFu': 5 | constructor: 6 | tt_args: 7 | ENCODING: UTF-8 8 | 9 | 'View::TT': 10 | ENCODING: UTF-8 11 | 12 | 'View::TT::Alloy': 13 | TEMPLATE_EXTENSION: '.tt' 14 | ENCODING: UTF-8 15 | -------------------------------------------------------------------------------- /examples/vertically-aligned-css/test.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FormFu/HTML-FormFu/17eb6f1fb450dbd339efed9e4f6b6d53a5d35638/examples/vertically-aligned-css/test.jpg -------------------------------------------------------------------------------- /examples/vertically-aligned-css/vertically-aligned-ie.css: -------------------------------------------------------------------------------- 1 | /* MS Internet Explorer specific styles */ 2 | 3 | fieldset.radiogroup, 4 | fieldset.checkboxgroup 5 | { 6 | padding-top: 0; 7 | } 8 | -------------------------------------------------------------------------------- /examples/vertically-aligned-css/vertically-aligned.pl: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use lib 'lib'; 4 | use HTML::FormFu; 5 | use Template; 6 | 7 | my $form = HTML::FormFu->new; 8 | 9 | $form->load_config_file('examples/vertically-aligned-css/vertically-aligned.yml'); 10 | 11 | my $tt = Template->new; 12 | 13 | $tt->process( 14 | 'examples/vertically-aligned-css/vertically-aligned.tt', 15 | { form => $form }, 16 | 'examples/vertically-aligned-css/vertically-aligned.html', 17 | ) || die $tt->error; 18 | -------------------------------------------------------------------------------- /examples/vertically-aligned-css/vertically-aligned.tt: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | Vertically Aligned 6 | 7 | 10 | 15 | 16 | 17 | 18 | [% form %] 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /lib/HTML/FormFu/Constants.pm: -------------------------------------------------------------------------------- 1 | use strict; 2 | 3 | package HTML::FormFu::Constants; 4 | # ABSTRACT: FormFU constants EMPTY_STR and SPACE 5 | 6 | use warnings; 7 | 8 | use Readonly; 9 | use Exporter qw( import ); 10 | 11 | Readonly our $EMPTY_STR => q{}; 12 | Readonly our $SPACE => q{ }; 13 | 14 | our @EXPORT_OK = qw( 15 | $EMPTY_STR 16 | $SPACE 17 | ); 18 | 19 | 1; 20 | -------------------------------------------------------------------------------- /lib/HTML/FormFu/Exception.pm: -------------------------------------------------------------------------------- 1 | use strict; 2 | 3 | package HTML::FormFu::Exception; 4 | # ABSTRACT: Exception base class 5 | 6 | use Moose; 7 | 8 | with 'HTML::FormFu::Role::Populate'; 9 | 10 | use HTML::FormFu::ObjectUtil qw( form parent ); 11 | 12 | sub BUILD { } 13 | 14 | sub render_data { 15 | my $self = shift; 16 | 17 | my $render = $self->render_data_non_recursive( { @_ ? %{ $_[0] } : () } ); 18 | 19 | return $render; 20 | } 21 | 22 | sub render_data_non_recursive { 23 | my ( $self, $args ) = @_; 24 | 25 | my %render = ( 26 | parent => $self->parent, 27 | form => $self->form, 28 | $args ? %$args : (), 29 | ); 30 | 31 | return \%render; 32 | } 33 | 34 | __PACKAGE__->meta->make_immutable; 35 | 36 | 1; 37 | -------------------------------------------------------------------------------- /lib/HTML/FormFu/Exception/Constraint.pm: -------------------------------------------------------------------------------- 1 | use strict; 2 | 3 | package HTML::FormFu::Exception::Constraint; 4 | # ABSTRACT: Constraint exception 5 | 6 | use Moose; 7 | extends 'HTML::FormFu::Exception::Input'; 8 | 9 | sub stage { 10 | return 'constraint'; 11 | } 12 | 13 | sub constraint { 14 | return shift->processor(@_); 15 | } 16 | 17 | around render_data_non_recursive => sub { 18 | my ( $orig, $self, $args ) = @_; 19 | 20 | my $render = $self->$orig( 21 | { stage => $self->stage, 22 | constraint => $self->constraint, 23 | $args ? %$args : (), 24 | } ); 25 | 26 | return $render; 27 | }; 28 | 29 | __PACKAGE__->meta->make_immutable; 30 | 31 | 1; 32 | -------------------------------------------------------------------------------- /lib/HTML/FormFu/Exception/Inflator.pm: -------------------------------------------------------------------------------- 1 | use strict; 2 | 3 | package HTML::FormFu::Exception::Inflator; 4 | # ABSTRACT: Inflator exception 5 | 6 | use Moose; 7 | extends 'HTML::FormFu::Exception::Input'; 8 | 9 | sub stage { 10 | return 'inflator'; 11 | } 12 | 13 | sub inflator { 14 | return shift->processor(@_); 15 | } 16 | 17 | around render_data_non_recursive => sub { 18 | my ( $orig, $self, $args ) = @_; 19 | 20 | my $render = $self->$orig( 21 | { stage => $self->stage, 22 | inflator => $self->inflator, 23 | $args ? %$args : (), 24 | } ); 25 | 26 | return $render; 27 | }; 28 | 29 | __PACKAGE__->meta->make_immutable; 30 | 31 | 1; 32 | -------------------------------------------------------------------------------- /lib/HTML/FormFu/Exception/Transformer.pm: -------------------------------------------------------------------------------- 1 | use strict; 2 | 3 | package HTML::FormFu::Exception::Transformer; 4 | # ABSTRACT: Transformer exception 5 | 6 | use Moose; 7 | extends 'HTML::FormFu::Exception::Input'; 8 | 9 | sub stage { 10 | return 'transformer'; 11 | } 12 | 13 | sub transformer { 14 | return shift->processor(@_); 15 | } 16 | 17 | around render_data_non_recursive => sub { 18 | my ( $orig, $self, $args ) = @_; 19 | 20 | my $render = $self->$orig( 21 | { stage => $self->stage, 22 | transformer => $self->transformer, 23 | $args ? %$args : (), 24 | } ); 25 | 26 | return $render; 27 | }; 28 | 29 | __PACKAGE__->meta->make_immutable; 30 | 31 | 1; 32 | -------------------------------------------------------------------------------- /lib/HTML/FormFu/Exception/Validator.pm: -------------------------------------------------------------------------------- 1 | use strict; 2 | 3 | package HTML::FormFu::Exception::Validator; 4 | # ABSTRACT: Validator exception 5 | 6 | use Moose; 7 | extends 'HTML::FormFu::Exception::Input'; 8 | 9 | sub stage { 10 | return 'validator'; 11 | } 12 | 13 | sub validator { 14 | return shift->processor(@_); 15 | } 16 | 17 | around render_data_non_recursive => sub { 18 | my ( $orig, $self, $args ) = @_; 19 | 20 | my $render = $self->$orig( 21 | { stage => $self->stage, 22 | validator => $self->validator, 23 | $args ? %$args : (), 24 | } ); 25 | 26 | return $render; 27 | }; 28 | 29 | __PACKAGE__->meta->make_immutable; 30 | 31 | 1; 32 | -------------------------------------------------------------------------------- /lib/HTML/FormFu/Filter/NonNumeric.pm: -------------------------------------------------------------------------------- 1 | use strict; 2 | 3 | package HTML::FormFu::Filter::NonNumeric; 4 | 5 | # ABSTRACT: filter removing all non-numeric characters 6 | 7 | use Moose; 8 | extends 'HTML::FormFu::Filter::Regex'; 9 | 10 | sub match {qr/\D+/} 11 | 12 | __PACKAGE__->meta->make_immutable; 13 | 14 | 1; 15 | 16 | __END__ 17 | 18 | =head1 DESCRIPTION 19 | 20 | Remove all non-numeric characters. 21 | 22 | =head1 AUTHOR 23 | 24 | Carl Franks, C 25 | 26 | =head1 LICENSE 27 | 28 | This library is free software, you can redistribute it and/or modify it under 29 | the same terms as Perl itself. 30 | 31 | =cut 32 | -------------------------------------------------------------------------------- /lib/HTML/FormFu/Filter/Whitespace.pm: -------------------------------------------------------------------------------- 1 | use strict; 2 | 3 | package HTML::FormFu::Filter::Whitespace; 4 | 5 | # ABSTRACT: filter stripping all whitespace 6 | 7 | use Moose; 8 | extends 'HTML::FormFu::Filter::Regex'; 9 | 10 | sub match {qr/\s+/} 11 | 12 | __PACKAGE__->meta->make_immutable; 13 | 14 | 1; 15 | 16 | __END__ 17 | 18 | =head1 DESCRIPTION 19 | 20 | Removes all whitespace. 21 | 22 | =head1 AUTHOR 23 | 24 | Carl Franks, C 25 | 26 | Based on the original source code of L, by 27 | Sebastian Riedel, C 28 | 29 | =head1 LICENSE 30 | 31 | This library is free software, you can redistribute it and/or modify it under 32 | the same terms as Perl itself. 33 | 34 | =cut 35 | -------------------------------------------------------------------------------- /lib/HTML/FormFu/I18N.pm: -------------------------------------------------------------------------------- 1 | use strict; 2 | 3 | package HTML::FormFu::I18N; 4 | # ABSTRACT: localization base class 5 | 6 | use Moose; 7 | 8 | extends 'Locale::Maketext'; 9 | 10 | *loc = \&localize; 11 | 12 | sub localize { 13 | my $self = shift; 14 | 15 | return $self->maketext(@_); 16 | } 17 | 18 | __PACKAGE__->meta->make_immutable( inline_constructor => 0 ); 19 | 20 | 1; 21 | -------------------------------------------------------------------------------- /lib/HTML/FormFu/Literal.pm: -------------------------------------------------------------------------------- 1 | use strict; 2 | 3 | package HTML::FormFu::Literal; 4 | # ABSTRACT: a FormFu literal 5 | 6 | use warnings; 7 | 8 | use HTML::FormFu::Constants qw( $EMPTY_STR ); 9 | 10 | use overload 11 | '""' => sub { return join $EMPTY_STR, @{ $_[0] } }, 12 | fallback => 1; 13 | 14 | sub new { 15 | my $class = shift; 16 | 17 | return bless \@_, $class; 18 | } 19 | 20 | sub push { 21 | my ( $self, @args ) = @_; 22 | 23 | CORE::push( @{ $_[0] }, @args ); 24 | } 25 | 26 | sub unshift { 27 | my ( $self, @args ) = @_; 28 | 29 | CORE::unshift( @{ $_[0] }, @args ); 30 | } 31 | 32 | 1; 33 | -------------------------------------------------------------------------------- /lib/HTML/FormFu/Preload.pm: -------------------------------------------------------------------------------- 1 | use strict; 2 | 3 | package HTML::FormFu::Preload; 4 | # ABSTRACT: preload plugins 5 | 6 | use warnings; 7 | 8 | use HTML::FormFu; 9 | 10 | use Module::Pluggable ( 11 | search_path => [ qw( 12 | HTML::FormFu::Element 13 | HTML::FormFu::Constraint 14 | HTML::FormFu::Deflator 15 | HTML::FormFu::Filter 16 | HTML::FormFu::Inflator 17 | HTML::FormFu::Transformer 18 | HTML::FormFu::Validator 19 | HTML::FormFu::Plugin 20 | HTML::FormFu::OutputProcessor 21 | ) 22 | ], 23 | require => 1 24 | ); 25 | 26 | __PACKAGE__->plugins; 27 | 28 | 1; 29 | -------------------------------------------------------------------------------- /lib/HTML/FormFu/Role/HasParent.pm: -------------------------------------------------------------------------------- 1 | use strict; 2 | 3 | package HTML::FormFu::Role::HasParent; 4 | # ABSTRACT: HasParent role 5 | 6 | use Moose::Role; 7 | 8 | sub BUILD { 9 | my ( $self, $args ) = @_; 10 | 11 | # Moose's new() only handles attributes - not methods 12 | 13 | if ( exists $args->{parent} ) { 14 | $self->parent( delete $args->{parent} ); 15 | } 16 | 17 | return; 18 | } 19 | 20 | 1; 21 | -------------------------------------------------------------------------------- /share/templates/tt/xhtml/block: -------------------------------------------------------------------------------- 1 | [% INCLUDE start_block %] 2 | [% IF self.content.defined %][% self.content %] 3 | [% ELSE %][% FOREACH element = self.elements %][% INCLUDE $element.filename self = element %] 4 | [% END %][% END %][% INCLUDE end_block %] -------------------------------------------------------------------------------- /share/templates/tt/xhtml/end_block: -------------------------------------------------------------------------------- 1 | [% IF self.tag.defined %][% END %] -------------------------------------------------------------------------------- /share/templates/tt/xhtml/end_form: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /share/templates/tt/xhtml/field: -------------------------------------------------------------------------------- 1 | [% IF self.container_tag.defined %]<[% self.container_tag %][% process_attrs(self.container_attributes) %]> 2 | [% END %][% content %][% IF self.container_tag.defined %] 3 | [% END %] -------------------------------------------------------------------------------- /share/templates/tt/xhtml/field_layout: -------------------------------------------------------------------------------- 1 | [% WRAPPER field %][% INCLUDE $self.layout_parser_filename layout=self.layout %][% END %] -------------------------------------------------------------------------------- /share/templates/tt/xhtml/field_layout_block: -------------------------------------------------------------------------------- 1 | [% tag=arguments.shift; opts=arguments.shift %]<[% tag %][% IF opts.attributes %][% process_attrs(opts.attributes) %][% END %]> 2 | [% IF opts.content %][% INCLUDE $self.layout_parser_filename layout=opts.content %] 3 | [% END %] -------------------------------------------------------------------------------- /share/templates/tt/xhtml/field_layout_comment: -------------------------------------------------------------------------------- 1 | [% IF self.comment.defined %] 2 | [% self.comment %] 3 | [% END %] -------------------------------------------------------------------------------- /share/templates/tt/xhtml/field_layout_contentbutton_field: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /share/templates/tt/xhtml/field_layout_errors: -------------------------------------------------------------------------------- 1 | [% IF self.errors 2 | %][% IF self.error_container_tag.defined 3 | %]<[% self.error_container_tag %][% process_attrs(self.error_container_attributes) %]> 4 | [% END 5 | %][% output = [] 6 | %][% FOREACH error = self.errors 7 | %][% item = [] 8 | %][% item.push("<", self.error_tag, process_attrs(error.attributes), ">", error.message, "" ) 9 | %][% output.push( item.join("") ) 10 | %][% END 11 | %][% output.join("\n") 12 | %][% IF self.error_container_tag.defined 13 | %] 14 | [% END 16 | %][% END -%] 17 | -------------------------------------------------------------------------------- /share/templates/tt/xhtml/field_layout_field: -------------------------------------------------------------------------------- 1 | [% IF self.datalist_options %][% FOREACH option = self.datalist_options %] 2 | [% END %] 3 | 4 | [% END %] -------------------------------------------------------------------------------- /share/templates/tt/xhtml/field_layout_javascript: -------------------------------------------------------------------------------- 1 | [% IF self.javascript.defined %] 2 | [% END %] -------------------------------------------------------------------------------- /share/templates/tt/xhtml/field_layout_label: -------------------------------------------------------------------------------- 1 | [% tag=''; opts={} 2 | %][% IF arguments.size 3 | %][% tag = arguments.shift; 4 | content = arguments.shift; 5 | opts.content = content; 6 | opts.attributes = self.label_attributes; 7 | %][% INCLUDE $self.layout_block_filename arguments=[tag, opts] 8 | %][% ELSE 9 | %][% IF self.label.defined %]<[% self.label_tag %][% process_attrs(self.label_attributes) %]>[% self.label %][% END 11 | %][% END %] -------------------------------------------------------------------------------- /share/templates/tt/xhtml/field_layout_label_field: -------------------------------------------------------------------------------- 1 | <[% self.tag %] name="[% self.nested_name %]"[% process_attrs(self.attributes) %]>[% self.value %] -------------------------------------------------------------------------------- /share/templates/tt/xhtml/field_layout_label_text: -------------------------------------------------------------------------------- 1 | [% IF self.label.defined %][% self.label %][% END %] -------------------------------------------------------------------------------- /share/templates/tt/xhtml/field_layout_multi_field: -------------------------------------------------------------------------------- 1 | 2 | [% FOREACH element = self.elements %][% INCLUDE $element.layout_parser_filename self=element layout=element.multi_layout %] 3 | [% END %] -------------------------------------------------------------------------------- /share/templates/tt/xhtml/field_layout_select_field: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /share/templates/tt/xhtml/field_layout_textarea_field: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /share/templates/tt/xhtml/form: -------------------------------------------------------------------------------- 1 | [% INCLUDE start_form %] 2 | [% FOREACH element = self.elements %][% INCLUDE $element.filename self=element %] 3 | [% END %][% INCLUDE end_form %] 4 | -------------------------------------------------------------------------------- /share/templates/tt/xhtml/non_block: -------------------------------------------------------------------------------- 1 | <[% self.tag %][% process_attrs(self.attributes) %] /> -------------------------------------------------------------------------------- /share/templates/tt/xhtml/recaptcha: -------------------------------------------------------------------------------- 1 | [% WRAPPER field %] 2 | [% self.recaptcha_html %][% END %] -------------------------------------------------------------------------------- /share/templates/tt/xhtml/repeatable: -------------------------------------------------------------------------------- 1 | [% FOREACH element = self.elements %][% INCLUDE $element.filename self = element %][% UNLESS loop.last %] 2 | [% END %][% END %] -------------------------------------------------------------------------------- /share/templates/tt/xhtml/start_block: -------------------------------------------------------------------------------- 1 | [% IF self.tag.defined %]<[% self.tag %][% process_attrs(self.attributes) %]>[% END %][% IF self.legend.defined %] 2 | [% self.legend %][% END %] -------------------------------------------------------------------------------- /share/templates/tt/xhtml/start_form: -------------------------------------------------------------------------------- 1 | [% IF self.form_error_message.defined %] 2 |
[% self.form_error_message %]
[% END %][% IF self.javascript_src.defined %][% FOREACH src = self.javascript_src.list %] 3 | [% END %][% END %][% IF self.javascript.defined %] 5 | [% END %] -------------------------------------------------------------------------------- /t/01use.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 3; 5 | 6 | use_ok('HTML::FormFu'); 7 | 8 | use_ok('HTML::FormFu::Preload'); 9 | 10 | ok( $INC{'HTML/FormFu/Element/Text.pm'} ); 11 | -------------------------------------------------------------------------------- /t/04basic.yml: -------------------------------------------------------------------------------- 1 | --- 2 | action: /foo/bar 3 | id: form 4 | auto_id: '%n' 5 | elements: 6 | - type: Fieldset 7 | legend: Jimi 8 | elements: 9 | - name: age 10 | type: Text 11 | comment: x 12 | label: Age 13 | constraints: [Integer, Required] 14 | - name: name 15 | type: Text 16 | label: Name 17 | - name: ok 18 | type: Hidden 19 | value: OK 20 | constraints: 21 | type: Required 22 | name: name 23 | filters: 24 | - HTMLEscape 25 | -------------------------------------------------------------------------------- /t/05_repeated_render.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use Test::More tests => 2; 4 | 5 | use HTML::FormFu; 6 | 7 | my $form = HTML::FormFu->new( 8 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 9 | 10 | $form->load_config_file('t/04basic.yml'); 11 | 12 | # check output is still exactly the same after rendering again 13 | 14 | { 15 | my $html = "$form"; 16 | 17 | is( $html, "$form" ); 18 | } 19 | 20 | # and after submitted form 21 | 22 | { 23 | $form->process( { age => 'abc', } ); 24 | 25 | my $html = "$form"; 26 | 27 | is( $html, "$form" ); 28 | } 29 | -------------------------------------------------------------------------------- /t/bugs/constructor_arg_overwrites_default.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 4; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { elements => { 10 | type => 'Text', 11 | name => 'foo', 12 | label_filename => 'foofile', 13 | } } ); 14 | 15 | $form->element( 16 | { type => 'Text', 17 | name => 'bar', 18 | label_filename => 'barfile', 19 | } ); 20 | 21 | is( $form->get_field('foo')->label_filename, 'foofile' ); 22 | is( $form->get_field('bar')->label_filename, 'barfile' ); 23 | 24 | is( $form->get_field('foo')->render_data->{label_filename}, 'foofile' ); 25 | is( $form->get_field('bar')->render_data->{label_filename}, 'barfile' ); 26 | 27 | -------------------------------------------------------------------------------- /t/bugs/date_element_deflator.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | my $field = $form->element('Date')->name('foo'); 11 | 12 | $field->deflator( { type => 'Callback', callback => 'A::epoch2datetime' } ); 13 | 14 | $form->default_values( { foo => time() } ); 15 | 16 | eval { $form->process; }; 17 | 18 | ok( !$@ ); 19 | 20 | package A; 21 | use DateTime; 22 | 23 | sub epoch2datetime { 24 | my ($value) = @_; 25 | 26 | return DateTime->from_epoch( epoch => $value ); 27 | } 28 | -------------------------------------------------------------------------------- /t/bugs/date_element_empty_input.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->element('Date')->name('foo')->auto_inflate(1); 11 | 12 | # empty input 13 | 14 | $form->process( { 'foo_day', '', 'foo_month', '', 'foo_year', '', } ); 15 | 16 | ok( $form->submitted_and_valid ); 17 | 18 | -------------------------------------------------------------------------------- /t/bugs/disabled_select_default_value.yml: -------------------------------------------------------------------------------- 1 | --- 2 | auto_fieldset: 1 3 | 4 | elements: 5 | - type: Select 6 | name: select 7 | values: 8 | - 1 9 | - 2 10 | - 3 11 | empty_first: 1 12 | retain_default: 1 13 | attributes: 14 | disabled: disabled 15 | 16 | - type: Text 17 | name: text 18 | constraints: 19 | - Required 20 | 21 | - type: Submit 22 | name: submit 23 | -------------------------------------------------------------------------------- /t/bugs/element_parent.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | =pod 9 | 10 | Using auto_fieldset, elements were incorrectly getting the form 11 | as their parent, not the fieldset 12 | 13 | =cut 14 | 15 | my $form = HTML::FormFu->new; 16 | 17 | $form->auto_fieldset(1); 18 | 19 | my $foo = $form->element( { name => 'foo' } ); 20 | 21 | ok( $foo->parent == $form->get_element ); 22 | 23 | -------------------------------------------------------------------------------- /t/bugs/empty_block_with_nested_name.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | # https://rt.cpan.org/Ticket/Display.html?id=54967 5 | 6 | use Test::More tests => 1; 7 | 8 | use HTML::FormFu; 9 | 10 | my $form = HTML::FormFu->new; 11 | 12 | $form->load_config_file('t/bugs/empty_block_with_nested_name.yml'); 13 | 14 | $form->process( { foo => 'aaa', } ); 15 | 16 | is_deeply( [ $form->valid ], ['foo'] ); 17 | -------------------------------------------------------------------------------- /t/bugs/empty_block_with_nested_name.yml: -------------------------------------------------------------------------------- 1 | --- 2 | auto_fieldset: 1 3 | 4 | elements: 5 | - name: foo 6 | 7 | - type: Fieldset 8 | nested_name: bar 9 | elements: 10 | - type: Label 11 | name: baz 12 | -------------------------------------------------------------------------------- /t/bugs/error_msg.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 4; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | $form->element('Text')->name('foo'); 12 | 13 | $form->constraint('Required'); 14 | $form->constraint('Email'); 15 | 16 | { 17 | $form->process( { foo => 'cfranks@cpan', } ); 18 | 19 | ok( $form->has_errors('foo'), 'foo has errors' ); 20 | 21 | like( $form, qr/\QThis field must contain an email address/ ); 22 | } 23 | 24 | { 25 | $form->process( { foo => '', } ); 26 | 27 | ok( $form->has_errors('foo'), 'foo has errors' ); 28 | 29 | like( $form, qr/\QThis field is required/ ); 30 | } 31 | -------------------------------------------------------------------------------- /t/bugs/error_multiple_fields_same_name.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 4; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | $form->load_config_file('t/bugs/error_multiple_fields_same_name.yml'); 12 | 13 | $form->process( { foo => [qw( 1 a )], } ); 14 | 15 | my @fields = @{ $form->get_fields }; 16 | 17 | ok( !@{ $fields[0]->get_errors } ); 18 | is( scalar( @{ $fields[1]->get_errors } ), 1 ); 19 | 20 | unlike( $fields[0], qr/This field must be an integer/i ); 21 | like( $fields[1], qr/This field must be an integer/i ); 22 | -------------------------------------------------------------------------------- /t/bugs/error_multiple_fields_same_name.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - name: foo 4 | - name: foo 5 | constraints: 6 | - type: Integer 7 | -------------------------------------------------------------------------------- /t/bugs/field_no_name.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->element('Text'); 11 | $form->element('Text')->name('foo'); 12 | 13 | my $div = $form->element('Block'); 14 | $div->element('Text'); 15 | $div->element('Text')->name('bar'); 16 | 17 | $form->process( { foo => 1 } ); 18 | 19 | is( @{ $form->get_fields('foo') }, 1 ); 20 | 21 | { 22 | my $div = $form->get_element( { type => 'Block' } ); 23 | 24 | is( @{ $div->get_fields('bar') }, 1 ); 25 | } 26 | -------------------------------------------------------------------------------- /t/bugs/filter_run_once.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $count = 0; 9 | 10 | my $form = HTML::FormFu->new; 11 | 12 | $form->element('Text')->name('foo'); 13 | 14 | $form->filter( Callback => 'foo' )->callback( sub { $count++ } ); 15 | 16 | $form->process( { foo => 'whatever', } ); 17 | 18 | is( $count, 1 ); 19 | -------------------------------------------------------------------------------- /t/bugs/multiple_checkbox_same_name.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | $form->load_config_file('t/bugs/multiple_checkbox_same_name.yml'); 12 | 13 | $form->process( { foo => [qw( 1 2 )], } ); 14 | 15 | my $foo = $form->get_fields('foo'); 16 | 17 | like( $foo->[0], qr/checked="checked"/ ); 18 | like( $foo->[1], qr/checked="checked"/ ); 19 | -------------------------------------------------------------------------------- /t/bugs/multiple_checkbox_same_name.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - type: Checkbox 4 | name: foo 5 | value: 1 6 | - type: Checkbox 7 | name: foo 8 | value: 2 9 | -------------------------------------------------------------------------------- /t/bugs/name_regex_chars.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->element('Text')->name('foo/bar'); 11 | 12 | { 13 | $form->process( { 'foo/bar' => 'bam' } ); 14 | 15 | is( $form->param('foo/bar'), 'bam', 'foo/bar valid' ); 16 | } 17 | 18 | -------------------------------------------------------------------------------- /t/bugs/not_nested.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->auto_fieldset(1); 11 | 12 | my $field = $form->element('Text')->name('foo'); 13 | 14 | ok( !$field->nested ); 15 | -------------------------------------------------------------------------------- /t/bugs/populate_element_coderef.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; 5 | 6 | use HTML::FormFu; 7 | 8 | my $callback = sub { 9 | my $value = shift; 10 | 11 | Test::More::ok(1) if $value eq 'a'; 12 | 13 | return 1; 14 | }; 15 | 16 | my $form = HTML::FormFu->new; 17 | 18 | $form->populate( 19 | { elements => [ 20 | { name => 'foo', 21 | constraint => { 22 | type => 'Callback', 23 | callback => $callback, 24 | }, 25 | }, 26 | ], 27 | } ); 28 | 29 | # Valid 30 | { 31 | $form->process( { foo => 'a', } ); 32 | 33 | ok( $form->valid('foo'), 'foo valid' ); 34 | } 35 | -------------------------------------------------------------------------------- /t/bugs/pre_1_00_compat.yml: -------------------------------------------------------------------------------- 1 | --- 2 | id: formfu 3 | auto_fieldset: 1 4 | auto_id: '%f_%n' 5 | 6 | elements: 7 | - name: foo 8 | label: Foo 9 | comment: The Foo 10 | constraint: 11 | - type: Required 12 | 13 | # config to attain compatibility below 14 | auto_container_class: '%t' 15 | auto_container_label_class: 'label' 16 | auto_container_comment_class: 'comment' 17 | auto_comment_class: 'comment' 18 | auto_container_error_class: 'error' 19 | auto_container_per_error_class: 'error_%s_%t' 20 | auto_error_class: 'error_message error_%s_%t' 21 | -------------------------------------------------------------------------------- /t/bugs/render_processed_value_retain_default.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | use DateTime; 8 | 9 | my $form = HTML::FormFu->new( 10 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 11 | 12 | $form->load_config_file('t/bugs/render_processed_value_retain_default.yml'); 13 | 14 | # set default 15 | 16 | my $dt = DateTime->new( 17 | day => 7, 18 | month => 5, 19 | year => 2008, 20 | ); 21 | 22 | $form->get_field('foo')->default($dt); 23 | 24 | # don't submit foo 25 | 26 | $form->process( { submit => 'Submit', } ); 27 | 28 | # default is kept, and deflated 29 | like( $form->get_field('foo')->render, qr|value="07/05/2008"| ); 30 | -------------------------------------------------------------------------------- /t/bugs/render_processed_value_retain_default.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | elements: 4 | - name: foo 5 | render_processed_value: 1 6 | retain_default: 1 7 | deflator: 8 | - type: Strftime 9 | strftime: '%d/%m/%Y' 10 | 11 | - type: Submit 12 | name: submit 13 | 14 | -------------------------------------------------------------------------------- /t/bugs/repeatable_increase_rep.yml: -------------------------------------------------------------------------------- 1 | --- 2 | auto_fieldset: 1 3 | 4 | elements: 5 | - type: Repeatable 6 | increment_field_names: 0 7 | elements: 8 | - name: foo 9 | render_processed_value: 1 10 | filter: 11 | ForceListValue 12 | 13 | - type: Submit 14 | name: submit 15 | -------------------------------------------------------------------------------- /t/bugs/result_params_multiple.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->element('Text')->name('foo'); 11 | 12 | # Valid 13 | { 14 | $form->process( { foo => [ 'one', 'two' ] } ); 15 | 16 | ok( $form->valid('foo'), 'foo valid' ); 17 | 18 | my $params = $form->params; 19 | 20 | is_deeply( $params, { foo => [ 'one', 'two' ] } ); 21 | } 22 | -------------------------------------------------------------------------------- /t/bugs/select_empty_options.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; 5 | 6 | use HTML::FormFu; 7 | my $form = HTML::FormFu->new( 8 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 9 | 10 | $form->element('Select')->name('foo'); 11 | $form->element('Select')->name('bar')->options(); 12 | 13 | my $xhtml = < 15 |
16 | 18 |
19 |
20 | 22 |
23 | 24 | EOF 25 | 26 | eval { is( "$form", $xhtml ); }; 27 | 28 | ok( !$@, "died: $@" ); 29 | -------------------------------------------------------------------------------- /t/bugs/value_empty_string.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | $form->element('Text')->name('foo')->default(''); 12 | 13 | like( $form->get_field('foo'), qr/\Q value="" /x, 14 | 'empty value appears in XML' ); 15 | 16 | -------------------------------------------------------------------------------- /t/bugs/yaml_utf8.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use Encode 'encode'; 4 | 5 | use Test::More tests => 1; 6 | 7 | use HTML::FormFu; 8 | 9 | my $form = HTML::FormFu->new->load_config_file('t/bugs/yaml_utf8.yml'); 10 | 11 | open my $fh, '<:encoding(UTF-8)', 't/bugs/yaml_utf8.txt' 12 | or die $!; 13 | 14 | my $text = do { local $/; <$fh> }; 15 | chomp $text; 16 | 17 | is( $form->get_field('foo')->label, $text ); 18 | 19 | -------------------------------------------------------------------------------- /t/bugs/yaml_utf8.txt: -------------------------------------------------------------------------------- 1 | fü -------------------------------------------------------------------------------- /t/bugs/yaml_utf8.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - name: foo 4 | label: fü 5 | -------------------------------------------------------------------------------- /t/constraints/allornone_attach_errors_to_base.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 4; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->load_config_file('t/constraints/allornone_attach_errors_to_base.yml'); 11 | 12 | # Valid 13 | { 14 | $form->process( 15 | { foo => 'a', 16 | bar => 'b', 17 | } ); 18 | 19 | ok( $form->submitted_and_valid ); 20 | } 21 | 22 | # Invalid 23 | { 24 | $form->process( 25 | { foo => '', 26 | bar => 'b', 27 | } ); 28 | 29 | ok( !$form->submitted_and_valid ); 30 | 31 | ok( !$form->has_errors('foo') ); 32 | ok( $form->has_errors('bar') ); 33 | } 34 | -------------------------------------------------------------------------------- /t/constraints/allornone_attach_errors_to_base.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - name: foo 4 | 5 | - name: bar 6 | constraints: 7 | - type: AllOrNone 8 | others: foo 9 | attach_errors_to_base: 1 10 | 11 | -------------------------------------------------------------------------------- /t/constraints/allornone_attach_errors_to_others.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 4; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->load_config_file('t/constraints/allornone_attach_errors_to_others.yml'); 11 | 12 | # Valid 13 | { 14 | $form->process( 15 | { foo => 'a', 16 | bar => 'b', 17 | } ); 18 | 19 | ok( $form->submitted_and_valid ); 20 | } 21 | 22 | # Invalid 23 | { 24 | $form->process( 25 | { foo => '', 26 | bar => 'b', 27 | } ); 28 | 29 | ok( !$form->submitted_and_valid ); 30 | 31 | ok( $form->has_errors('foo') ); 32 | ok( !$form->has_errors('bar') ); 33 | } 34 | -------------------------------------------------------------------------------- /t/constraints/allornone_attach_errors_to_others.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - name: foo 4 | 5 | - name: bar 6 | constraints: 7 | - type: AllOrNone 8 | others: foo 9 | attach_errors_to_others: 10 | - foo 11 | -------------------------------------------------------------------------------- /t/constraints/ascii.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 4; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->element('Text')->name('foo'); 11 | $form->element('Text')->name('bar'); 12 | 13 | $form->constraint('ASCII'); 14 | 15 | # Valid 16 | { 17 | $form->process( 18 | { foo => 'aaa', 19 | bar => 'bbbbbbb', 20 | } ); 21 | 22 | ok( $form->valid('foo'), 'foo valid' ); 23 | ok( $form->valid('bar'), 'bar valid' ); 24 | } 25 | 26 | # Invalid 27 | { 28 | $form->process( 29 | { foo => 'aaa', 30 | bar => '日本語', 31 | } ); 32 | 33 | ok( $form->valid('foo'), 'foo valid' ); 34 | ok( !$form->valid('bar'), 'bar not valid' ); 35 | } 36 | 37 | -------------------------------------------------------------------------------- /t/constraints/bool.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 4; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->element('Text')->name('foo'); 11 | $form->element('Text')->name('bar'); 12 | 13 | $form->constraint('Bool'); 14 | 15 | # Valid 16 | { 17 | $form->process( 18 | { foo => 1, 19 | bar => 0, 20 | } ); 21 | 22 | ok( $form->valid('foo'), 'foo valid' ); 23 | ok( $form->valid('bar'), 'bar valid' ); 24 | } 25 | 26 | # Invalid 27 | { 28 | $form->process( 29 | { foo => '01', 30 | bar => 'a', 31 | } ); 32 | 33 | ok( !$form->valid('foo'), 'foo not valid' ); 34 | ok( !$form->valid('bar'), 'bar not valid' ); 35 | } 36 | 37 | -------------------------------------------------------------------------------- /t/constraints/constraint_other_siblings.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - name: foo 4 | constraints: 5 | - type: AllOrNone 6 | other_siblings: 1 7 | 8 | - name: bar 9 | 10 | - name: baz 11 | 12 | - name: bif 13 | -------------------------------------------------------------------------------- /t/constraints/constraint_other_siblings_not.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - name: foo 4 | constraints: 5 | - type: Equal 6 | other_siblings: 1 7 | not: 1 8 | 9 | - name: bar 10 | 11 | - name: baz 12 | -------------------------------------------------------------------------------- /t/constraints/constraint_when_any_field.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - name: a 4 | constraints: 5 | - type: MinMaxFields 6 | min: 1 7 | max: 2 8 | others: 9 | - 'b' 10 | - 'c' 11 | - 'd' 12 | when: 13 | any_field: 14 | - 'a' 15 | - 'b' 16 | - 'c' 17 | - 'd' 18 | 19 | - name: b 20 | 21 | - name: c 22 | 23 | - name: d 24 | -------------------------------------------------------------------------------- /t/constraints/constraint_when_any_true_value.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - name: foo 4 | 5 | - name: bar 6 | constraints: 7 | - type: Required 8 | when: 9 | field: foo 10 | -------------------------------------------------------------------------------- /t/constraints/constraint_when_default_empty_value.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - name: foo 4 | type: Checkbox 5 | default_empty_value: 1 6 | 7 | - name: bar 8 | constraints: 9 | - type: Required 10 | when: 11 | field: foo 12 | value: 1 13 | not: 1 14 | -------------------------------------------------------------------------------- /t/constraints/constraint_when_fields.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - name: a 4 | constraints: 5 | - type: Bool 6 | when: 7 | fields: 8 | - 'b' 9 | - 'c' 10 | 11 | - name: b 12 | 13 | - name: c 14 | -------------------------------------------------------------------------------- /t/constraints/datetime_parser.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 4; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | my $foo = $form->element('Text')->name('foo'); 11 | 12 | $foo->constraint('DateTime')->parser( { strptime => '%d/%m/%Y' } ); 13 | 14 | # valid 15 | { 16 | $form->process( { foo => '31/12/2006' } ); 17 | 18 | ok( $form->submitted_and_valid ); 19 | 20 | is( $form->params->{foo}, '31/12/2006' ); 21 | } 22 | 23 | # invalid 24 | { 25 | $form->process( { foo => '12/31/2006' } ); 26 | 27 | ok( !$form->submitted_and_valid ); 28 | 29 | ok( $form->has_errors('foo') ); 30 | } 31 | -------------------------------------------------------------------------------- /t/constraints/dependon_attach_errors_to_base.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 4; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->load_config_file('t/constraints/dependon_attach_errors_to_base.yml'); 11 | 12 | # Valid 13 | { 14 | $form->process( 15 | { foo => 'a', 16 | bar => 'b', 17 | } ); 18 | 19 | ok( $form->submitted_and_valid ); 20 | } 21 | 22 | # Invalid 23 | { 24 | $form->process( 25 | { foo => '', 26 | bar => 'b', 27 | } ); 28 | 29 | ok( !$form->submitted_and_valid ); 30 | 31 | ok( !$form->has_errors('foo') ); 32 | ok( $form->has_errors('bar') ); 33 | } 34 | -------------------------------------------------------------------------------- /t/constraints/dependon_attach_errors_to_base.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - name: foo 4 | 5 | - name: bar 6 | constraints: 7 | - type: DependOn 8 | others: foo 9 | attach_errors_to_base: 1 10 | -------------------------------------------------------------------------------- /t/constraints/dependon_attach_errors_to_others.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 4; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->load_config_file('t/constraints/dependon_attach_errors_to_others.yml'); 11 | 12 | # Valid 13 | { 14 | $form->process( 15 | { foo => 'a', 16 | bar => 'b', 17 | } ); 18 | 19 | ok( $form->submitted_and_valid ); 20 | } 21 | 22 | # Invalid 23 | { 24 | $form->process( 25 | { foo => '', 26 | bar => 'b', 27 | } ); 28 | 29 | ok( !$form->submitted_and_valid ); 30 | 31 | ok( $form->has_errors('foo') ); 32 | ok( !$form->has_errors('bar') ); 33 | } 34 | -------------------------------------------------------------------------------- /t/constraints/dependon_attach_errors_to_others.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - name: foo 4 | 5 | - name: bar 6 | constraints: 7 | - type: DependOn 8 | others: foo 9 | attach_errors_to_others: 10 | - foo 11 | -------------------------------------------------------------------------------- /t/constraints/equal_internals.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 5; 5 | 6 | use HTML::FormFu::Constraint::Equal; 7 | 8 | ok( HTML::FormFu::Constraint::Equal::_values_eq( '1', '1' ) ); 9 | ok( HTML::FormFu::Constraint::Equal::_values_eq( ' ', ' ' ) ); 10 | ok( HTML::FormFu::Constraint::Equal::_values_eq( 'aa', 'aa' ) ); 11 | ok( HTML::FormFu::Constraint::Equal::_values_eq( ['x'], ['x'] ) ); 12 | ok( HTML::FormFu::Constraint::Equal::_values_eq( [ 'a', 'b' ], [ 'b', 'a' ] ) ); 13 | -------------------------------------------------------------------------------- /t/constraints/file.yml: -------------------------------------------------------------------------------- 1 | --- 2 | action: 'http://www.perl.org/test.cgi' 3 | 4 | elements: 5 | - type: File 6 | name: hello_world 7 | 8 | - type: File 9 | name: does_not_exist_gif 10 | 11 | constraints: 12 | - type: File 13 | -------------------------------------------------------------------------------- /t/constraints/file_maxsize.yml: -------------------------------------------------------------------------------- 1 | --- 2 | action: 'http://www.perl.org/test.cgi' 3 | 4 | elements: 5 | - type: File 6 | name: hello_world 7 | constraints: 8 | - type: File::MaxSize 9 | max: 15 10 | -------------------------------------------------------------------------------- /t/constraints/file_mime.yml: -------------------------------------------------------------------------------- 1 | --- 2 | action: 'http://www.perl.org/test.cgi' 3 | 4 | elements: 5 | - type: File 6 | name: hello_world 7 | constraints: 8 | - type: File::MIME 9 | types: ['text/rtf', 'text/plain'] 10 | 11 | - type: File 12 | name: 100x100_gif 13 | constraints: 14 | - type: File::MIME 15 | regex: '^ image/.* \z' 16 | -------------------------------------------------------------------------------- /t/constraints/file_minsize.yml: -------------------------------------------------------------------------------- 1 | --- 2 | action: 'http://www.perl.org/test.cgi' 3 | 4 | elements: 5 | - type: File 6 | name: hello_world 7 | constraints: 8 | - type: File::MinSize 9 | min: 1 10 | -------------------------------------------------------------------------------- /t/constraints/file_size.yml: -------------------------------------------------------------------------------- 1 | --- 2 | action: 'http://www.perl.org/test.cgi' 3 | 4 | elements: 5 | - type: File 6 | name: hello_world 7 | constraints: 8 | - type: File::Size 9 | min: 1 10 | max: 15 11 | 12 | - type: File 13 | name: does_not_exist_gif 14 | constraints: 15 | - type: File::Size 16 | min: 1 17 | max: 15 18 | -------------------------------------------------------------------------------- /t/constraints/json.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 4; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->element('Text')->name('foo'); 11 | 12 | $form->constraint('JSON'); 13 | 14 | my @valid = ( '{"foo":"bar"}', '[1,2]', ); 15 | 16 | for my $string (@valid) { 17 | $form->process( { foo => $string, } ); 18 | 19 | ok( $form->valid('foo'), "foo valid: $string" ); 20 | } 21 | 22 | my @invalid = ( "{'foo':'bar'}", 'plain text', ); 23 | 24 | for my $string (@invalid) { 25 | $form->process( { foo => $string, } ); 26 | 27 | ok( !$form->valid('foo'), "foo not valid: $string" ); 28 | } 29 | -------------------------------------------------------------------------------- /t/constraints/length.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 4; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->element('Text')->name('foo')->constraint('Length')->min(3)->max(5); 11 | $form->element('Text')->name('bar')->constraint('Length')->min(3)->max(5); 12 | 13 | # Valid 14 | { 15 | $form->process( 16 | { foo => 'abc', 17 | bar => 'abcd', 18 | } ); 19 | 20 | ok( $form->valid('foo'), 'foo valid' ); 21 | ok( $form->valid('bar'), 'bar valid' ); 22 | } 23 | 24 | # Invalid 25 | { 26 | $form->process( 27 | { foo => 'ab', 28 | bar => 'abcdef', 29 | } ); 30 | 31 | ok( !$form->valid('foo'), 'foo not valid' ); 32 | ok( !$form->valid('bar'), 'bar not valid' ); 33 | } 34 | -------------------------------------------------------------------------------- /t/constraints/localize.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | $form->element('Text')->name('foo'); 12 | 13 | $form->constraint('Required'); 14 | $form->constraint('MinLength')->min(3); 15 | 16 | $form->constraint('Regex')->regex(qr/^\d+$/) 17 | ->message_loc('form_constraint_integer'); 18 | 19 | $form->process( { foo => 'a' } ); 20 | 21 | like( $form->get_field('foo'), qr/This field must be an integer/ ); 22 | 23 | like( $form->get_field('foo'), qr/Must be at least 3 characters long/ ); 24 | -------------------------------------------------------------------------------- /t/constraints/maxrange.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 4; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->element('Text')->name('foo')->constraint('MaxRange')->max(5); 11 | $form->element('Text')->name('bar')->constraint('MaxRange')->max(5); 12 | 13 | # Valid 14 | { 15 | $form->process( 16 | { foo => 3, 17 | bar => 4, 18 | } ); 19 | 20 | ok( $form->valid('foo'), 'foo valid' ); 21 | ok( $form->valid('bar'), 'bar valid' ); 22 | } 23 | 24 | # Invalid 25 | { 26 | $form->process( 27 | { foo => 1, 28 | bar => 6, 29 | } ); 30 | 31 | ok( $form->valid('foo'), 'foo not valid' ); 32 | ok( !$form->valid('bar'), 'bar not valid' ); 33 | } 34 | -------------------------------------------------------------------------------- /t/constraints/minmaxfields_with_filter_split.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - name: foo 4 | constraints: 5 | - type: MinMaxFields 6 | others: 7 | - bar 8 | - baz 9 | min: 0 10 | max: 1 11 | filters: 12 | - type: Split 13 | regex: ',' 14 | 15 | - name: bar 16 | filters: 17 | - type: Split 18 | regex: ',' 19 | 20 | - name: baz 21 | filters: 22 | - type: Split 23 | regex: ',' 24 | -------------------------------------------------------------------------------- /t/constraints/minrange.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 4; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->element('Text')->name('foo')->constraint('MinRange')->min(3); 11 | $form->element('Text')->name('bar')->constraint('MinRange')->min(3); 12 | 13 | # Valid 14 | { 15 | $form->process( 16 | { foo => 3, 17 | bar => 4, 18 | } ); 19 | 20 | ok( $form->valid('foo'), 'foo valid' ); 21 | ok( $form->valid('bar'), 'bar valid' ); 22 | } 23 | 24 | # Invalid 25 | { 26 | $form->process( 27 | { foo => 1, 28 | bar => 6, 29 | } ); 30 | 31 | ok( !$form->valid('foo'), 'foo not valid' ); 32 | ok( $form->valid('bar'), 'bar not valid' ); 33 | } 34 | -------------------------------------------------------------------------------- /t/constraints/not_equal.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 4; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->element('Text')->name('foo')->constraint('Not_Equal')->others('bar'); 11 | $form->element('Text')->name('bar'); 12 | 13 | # Valid 14 | { 15 | $form->process( 16 | { foo => 'yada', 17 | bar => 'xxxx', 18 | } ); 19 | 20 | ok( $form->valid('foo'), 'foo valid' ); 21 | ok( $form->valid('bar'), 'bar valid' ); 22 | } 23 | 24 | # Invalid 25 | { 26 | $form->process( 27 | { foo => 'yada', 28 | bar => 'yada', 29 | } ); 30 | 31 | ok( $form->valid('foo'), 'foo valid' ); 32 | ok( $form->has_errors('bar'), 'bar valid' ); 33 | } 34 | -------------------------------------------------------------------------------- /t/constraints/not_word.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 4; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->element('Text')->name('foo'); 11 | $form->element('Text')->name('bar'); 12 | 13 | $form->constraint('Not_Word'); 14 | 15 | # Valid 16 | { 17 | $form->process( 18 | { foo => ' ', 19 | bar => "\t", 20 | } ); 21 | 22 | ok( $form->valid('foo'), 'foo valid' ); 23 | ok( $form->valid('bar'), 'bar valid' ); 24 | } 25 | 26 | # Invalid 27 | { 28 | $form->process( 29 | { foo => 'a', 30 | bar => "\n", 31 | } ); 32 | 33 | ok( $form->has_errors('foo'), 'foo has_errors' ); 34 | ok( $form->valid('bar'), 'bar valid' ); 35 | } 36 | -------------------------------------------------------------------------------- /t/constraints/printable.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 4; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->element('Text')->name('foo'); 11 | $form->element('Text')->name('bar'); 12 | 13 | $form->constraint('Printable'); 14 | 15 | # Valid 16 | { 17 | $form->process( 18 | { foo => 'aaa', 19 | bar => 'bbbbbbb', 20 | } ); 21 | 22 | ok( $form->valid('foo'), 'foo valid' ); 23 | ok( $form->valid('bar'), 'bar valid' ); 24 | } 25 | 26 | # Invalid 27 | { 28 | $form->process( 29 | { foo => 'aaa', 30 | bar => '日本語', 31 | } ); 32 | 33 | ok( $form->valid('foo'), 'foo valid' ); 34 | ok( $form->has_errors('bar'), 'bar has errors' ); 35 | } 36 | 37 | -------------------------------------------------------------------------------- /t/constraints/range.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 4; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->element('Text')->name('foo')->constraint('Range')->min(3)->max(5); 11 | $form->element('Text')->name('bar')->constraint('Range')->min(3)->max(5); 12 | 13 | # Valid 14 | { 15 | $form->process( 16 | { foo => 3, 17 | bar => 4, 18 | } ); 19 | 20 | ok( $form->valid('foo'), 'foo valid' ); 21 | ok( $form->valid('bar'), 'bar valid' ); 22 | } 23 | 24 | # Invalid 25 | { 26 | $form->process( 27 | { foo => 1, 28 | bar => 6, 29 | } ); 30 | 31 | ok( !$form->valid('foo'), 'foo not valid' ); 32 | ok( !$form->valid('bar'), 'bar not valid' ); 33 | } 34 | -------------------------------------------------------------------------------- /t/constraints/repeatable_any.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - type: Hidden 4 | name: count 5 | 6 | - type: Repeatable 7 | counter_name: count 8 | elements: 9 | - name: foo 10 | constraints: 11 | - 'Repeatable::Any' 12 | -------------------------------------------------------------------------------- /t/constraints/repeatable_any_not_increment_field_n.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - type: Hidden 4 | name: count 5 | 6 | - type: Repeatable 7 | counter_name: count 8 | increment_field_names: 0 9 | elements: 10 | - name: foo 11 | constraints: 12 | - 'Repeatable::Any' 13 | -------------------------------------------------------------------------------- /t/constraints/required_file.yml: -------------------------------------------------------------------------------- 1 | --- 2 | action: 'http://www.perl.org/test.cgi' 3 | 4 | elements: 5 | - type: File 6 | name: multiple 7 | 8 | - type: File 9 | name: hello_world 10 | 11 | constraints: 12 | - type: Required 13 | 14 | -------------------------------------------------------------------------------- /t/constraints/required_only_on_reps.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - type: Hidden 4 | name: count 5 | 6 | - type: Repeatable 7 | counter_name: count 8 | elements: 9 | - name: foo 10 | constraints: 11 | - type: Required 12 | only_on_reps: 1 13 | 14 | - name: bar 15 | constraints: 16 | - type: Required 17 | only_on_reps: 2 18 | 19 | - name: buz 20 | constraints: 21 | - type: Required 22 | only_on_reps: [1, 3] 23 | 24 | - name: moo 25 | constraints: 26 | - type: Required 27 | -------------------------------------------------------------------------------- /t/constraints/singlevalue.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->element('Text')->name('foo'); 11 | $form->element('Text')->name('bar'); 12 | $form->element('Text')->name('baz'); 13 | $form->element('Text')->name('bif'); 14 | $form->element('Text')->name('bom'); 15 | 16 | $form->constraint('SingleValue'); 17 | 18 | $form->process( 19 | { foo => 1, 20 | bar => '', 21 | baz => [2], 22 | bif => [ 3, 4 ], 23 | } ); 24 | 25 | is_deeply( [ $form->has_errors ], ['bif'] ); 26 | 27 | -------------------------------------------------------------------------------- /t/constraints/xml.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | $form->element('Text')->name('foo'); 12 | 13 | $form->constraint('Required'); 14 | $form->constraint('Regex')->regex(qr/^\d+$/)->message_xml("don't escape "); 15 | 16 | $form->process( { foo => 'a' } ); 17 | 18 | like( $form->get_field('foo'), qr/don't escape / ); 19 | -------------------------------------------------------------------------------- /t/deflators/compounddatetime.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | elements: 4 | - type: Multi 5 | name: dob 6 | 7 | elements: 8 | - name: day 9 | - name: month 10 | - name: year 11 | 12 | deflator: 13 | - type: CompoundDateTime 14 | -------------------------------------------------------------------------------- /t/deflators/compounddatetime_field_order.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | elements: 4 | - type: Multi 5 | name: dob 6 | 7 | elements: 8 | - name: m 9 | - name: d 10 | - name: y 11 | 12 | deflator: 13 | - type: CompoundDateTime 14 | field_order: ['month', 'day', 'year'] 15 | -------------------------------------------------------------------------------- /t/deflators/compoundsplit.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | $form->load_config_file('t/deflators/compoundsplit.yml'); 12 | 13 | $form->default_values( { address => '10 Downing Street', } ); 14 | 15 | $form->process; 16 | 17 | my $html = < 19 |
20 | 21 | 22 | 23 | 24 |
25 | 26 | HTML 27 | 28 | is( "$form", $html ); 29 | -------------------------------------------------------------------------------- /t/deflators/compoundsplit.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | elements: 4 | - type: Multi 5 | name: address 6 | 7 | elements: 8 | - name: number 9 | - name: street 10 | 11 | deflators: 12 | type: CompoundSplit 13 | -------------------------------------------------------------------------------- /t/deflators/compoundsplit_after_submit.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | elements: 4 | - type: Multi 5 | name: address 6 | 7 | elements: 8 | - name: number 9 | - name: street 10 | 11 | filters: 12 | type: CompoundJoin 13 | 14 | deflators: 15 | type: CompoundSplit 16 | -------------------------------------------------------------------------------- /t/deflators/compoundsplit_field_order.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | $form->load_config_file('t/deflators/compoundsplit_field_order.yml'); 12 | 13 | $form->default_values( { address => '10 Downing Street', } ); 14 | 15 | $form->process; 16 | 17 | my $html = < 19 |
20 | 21 | 22 | 23 | 24 |
25 | 26 | HTML 27 | 28 | is( "$form", $html ); 29 | -------------------------------------------------------------------------------- /t/deflators/compoundsplit_field_order.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | elements: 4 | - type: Multi 5 | name: address 6 | 7 | elements: 8 | - name: street 9 | - name: number 10 | 11 | deflators: 12 | type: CompoundSplit 13 | field_order: 14 | - number 15 | - street 16 | -------------------------------------------------------------------------------- /t/deflators/compoundsplit_split.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | $form->load_config_file('t/deflators/compoundsplit_split.yml'); 12 | 13 | $form->default_values( { sortcode => '01-02-03', } ); 14 | 15 | $form->process; 16 | 17 | my $html = < 19 |
20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | HTML 28 | 29 | is( "$form", $html ); 30 | -------------------------------------------------------------------------------- /t/deflators/compoundsplit_split.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | elements: 4 | - type: Multi 5 | name: sortcode 6 | 7 | elements: 8 | - name: p1 9 | - name: p2 10 | - name: p3 11 | 12 | deflators: 13 | type: CompoundSplit 14 | split: '-' 15 | -------------------------------------------------------------------------------- /t/deflators/formatnumber.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - name: foo 4 | deflators: 5 | - type: FormatNumber 6 | precision: 8 7 | trailing_zeroes: 1 8 | -------------------------------------------------------------------------------- /t/elements-file_post.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FormFu/HTML-FormFu/17eb6f1fb450dbd339efed9e4f6b6d53a5d35638/t/elements-file_post.txt -------------------------------------------------------------------------------- /t/elements/block_auto_block_id.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | $form->load_config_file('t/elements/block_auto_block_id.yml'); 12 | 13 | is( "$form", < 15 |
16 | Hello 17 |
18 | 19 | EOF 20 | -------------------------------------------------------------------------------- /t/elements/block_auto_block_id.yml: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'form' 3 | 4 | elements: 5 | - type: Block 6 | auto_block_id: '%f_block' 7 | content: 'Hello' 8 | -------------------------------------------------------------------------------- /t/elements/block_repeatable.yml: -------------------------------------------------------------------------------- 1 | --- 2 | auto_fieldset: 1 3 | 4 | elements: 5 | - type: Repeatable 6 | elements: 7 | - name: foo 8 | - name: bar 9 | - type: Submit 10 | name: submit 11 | -------------------------------------------------------------------------------- /t/elements/block_repeatable_attrs.yml: -------------------------------------------------------------------------------- 1 | --- 2 | auto_fieldset: 1 3 | 4 | elements: 5 | - type: Repeatable 6 | attrs: 7 | class: repeat 8 | elements: 9 | - name: foo 10 | - name: bar 11 | - type: Submit 12 | name: submit 13 | -------------------------------------------------------------------------------- /t/elements/block_repeatable_auto_block_id.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - type: Repeatable 4 | elements: 5 | - type: Block 6 | tag: span 7 | auto_block_id: 'inner_%r' 8 | elements: 9 | - name: foo 10 | - name: bar 11 | -------------------------------------------------------------------------------- /t/elements/block_repeatable_auto_id.yml: -------------------------------------------------------------------------------- 1 | --- 2 | auto_fieldset: 1 3 | 4 | elements: 5 | - type: Repeatable 6 | increment_field_names: 0 7 | auto_id: "%n_%r" 8 | elements: 9 | - name: foo 10 | - name: bar 11 | - type: Submit 12 | name: submit 13 | -------------------------------------------------------------------------------- /t/elements/block_repeatable_date.yml: -------------------------------------------------------------------------------- 1 | --- 2 | auto_fieldset: 1 3 | 4 | elements: 5 | - type: Repeatable 6 | elements: 7 | - name: foo 8 | type: Date 9 | year: 10 | reference: 2008 11 | -------------------------------------------------------------------------------- /t/elements/block_repeatable_inc.yml: -------------------------------------------------------------------------------- 1 | --- 2 | auto_fieldset: 1 3 | 4 | elements: 5 | - type: Repeatable 6 | 7 | # it's now the default behaviour 8 | # increment_field_names: 1 9 | 10 | elements: 11 | - name: foo 12 | - name: bar 13 | - type: Submit 14 | name: submit 15 | -------------------------------------------------------------------------------- /t/elements/block_repeatable_tag.yml: -------------------------------------------------------------------------------- 1 | --- 2 | auto_fieldset: 1 3 | 4 | elements: 5 | - type: Repeatable 6 | tag: fieldset 7 | elements: 8 | - name: foo 9 | - name: bar 10 | - type: Submit 11 | name: submit 12 | -------------------------------------------------------------------------------- /t/elements/button.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | my $field = $form->element('Button')->name('foo'); 12 | 13 | my $field_xhtml = qq{
14 | 15 |
}; 16 | 17 | is( "$field", $field_xhtml, 'stringified field' ); 18 | 19 | my $form_xhtml = < 21 | $field_xhtml 22 | 23 | EOF 24 | 25 | is( "$form", $form_xhtml, 'stringified form' ); 26 | 27 | -------------------------------------------------------------------------------- /t/elements/button_no_name.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | my $field = $form->element('Button'); 12 | 13 | my $field_xhtml = qq{
14 | 15 |
}; 16 | 17 | is( "$field", $field_xhtml, 'stringified field' ); 18 | 19 | -------------------------------------------------------------------------------- /t/elements/checkbox_reverse.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | $form->load_config_file('t/elements/checkbox_reverse.yml'); 12 | 13 | my $form_xhtml = < 15 |
16 | 17 | 18 |
19 |
20 | 21 | 22 |
23 | 24 | EOF 25 | 26 | is( $form, $form_xhtml ); 27 | -------------------------------------------------------------------------------- /t/elements/checkbox_reverse.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - type: Checkbox 4 | name: foo 5 | label: Foo 6 | 7 | - type: Checkbox 8 | name: bar 9 | label: Bar 10 | reverse_single: 1 11 | -------------------------------------------------------------------------------- /t/elements/checkboxgroup_attributes_escaped.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - type: Checkboxgroup 4 | name: foo 5 | options: 6 | - value: 1 7 | label: 'First' 8 | attributes: 9 | myattr: 'escape&attr' 10 | label_attributes: 11 | myattr: 'escape&label' 12 | container_attributes: 13 | myattr: 'escape&container' 14 | 15 | - value: 2 16 | label: 'Second' 17 | attributes_xml: 18 | myattr: 'noescape&' 19 | -------------------------------------------------------------------------------- /t/elements/combobox.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - type: ComboBox 4 | name: combo 5 | values: 6 | - one 7 | - two 8 | - three 9 | -------------------------------------------------------------------------------- /t/elements/combobox_repeatable.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - type: Repeatable 4 | name: container 5 | counter_name: count 6 | increment_field_names: 1 7 | elements: 8 | - type: ComboBox 9 | name: combo 10 | values: 11 | - one 12 | - two 13 | - three 14 | -------------------------------------------------------------------------------- /t/elements/combobox_required.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - type: ComboBox 4 | name: combo 5 | values: 6 | - one 7 | - two 8 | - three 9 | constraints: 10 | - Required 11 | 12 | - type: Submit 13 | name: submit 14 | -------------------------------------------------------------------------------- /t/elements/date_default_datetime_args.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - type: DateTime 4 | name: foo 5 | default_natural: now 6 | default_datetime_args: 7 | set_time_zone: Europe/Berlin 8 | 9 | - type: DateTime 10 | name: bar 11 | year: 12 | reference: 2000 13 | default_natural: now 14 | default_datetime_args: 15 | set_year: 2004 16 | -------------------------------------------------------------------------------- /t/elements/date_natural.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 3; 5 | 6 | use HTML::FormFu; 7 | use DateTime; 8 | 9 | { 10 | my $today = DateTime->today; 11 | my $form = HTML::FormFu->new; 12 | my $e = $form->element('Date'); 13 | $e->name('foo')->default_natural('today'); 14 | 15 | $form->process; 16 | 17 | for (qw( day month year )) { 18 | is( $e->$_->{default}, $today->$_ ); 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /t/elements/date_order_error.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; 5 | 6 | use HTML::FormFu; 7 | 8 | { 9 | my $form = HTML::FormFu->new; 10 | 11 | eval { 12 | my $element = $form->element('Date'); 13 | $element->name('date'); 14 | $element->field_order( [qw/ month day foo /] ); 15 | $form->process; 16 | }; 17 | 18 | ok($@); 19 | } 20 | 21 | { 22 | my $form = HTML::FormFu->new; 23 | 24 | eval { 25 | my $element = $form->element('Date'); 26 | $element->name('date'); 27 | $form->process; 28 | $element->field_order( [qw/ month month day /] )->value('01-01-2007'); 29 | }; 30 | 31 | ok($@); 32 | } 33 | -------------------------------------------------------------------------------- /t/elements/date_rename.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | my $date = $form->element('Date')->name('foo'); 12 | 13 | $form->process; 14 | 15 | # change name 16 | 17 | $date->name('bar'); 18 | 19 | $form->process; 20 | 21 | like( "$form", qr/name="bar_day"/ ); 22 | -------------------------------------------------------------------------------- /t/elements/date_undef.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | $form->populate( 12 | { elements => [ 13 | { type => "Date", 14 | name => "foo", 15 | year => { list => [2009] }, 16 | default => '30-08-2009' 17 | } ] } ); 18 | 19 | $form->process; 20 | 21 | like( $form->render, qr/value="2009" selected="selected"/ ); 22 | 23 | $form->get_field('foo')->default(undef); 24 | 25 | like( $form->render, qr/value="2009">/ ); 26 | -------------------------------------------------------------------------------- /t/elements/date_year_reverse.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - type: Date 4 | name: foo 5 | year: 6 | list: [2009, 2010, 2011] 7 | reverse: 1 8 | -------------------------------------------------------------------------------- /t/elements/datetime.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - type: DateTime 4 | name: foo 5 | strftime: '%m/%d/%Y %H:%M' 6 | day: 7 | prefix: '-- Day --' 8 | month: 9 | prefix: '-- Month --' 10 | short_names: 1 11 | year: 12 | prefix: '-- Year --' 13 | list: [2007, 2008, 2009, 2010, 2011] 14 | auto_inflate: 1 15 | constraints: 16 | - Required 17 | 18 | - type: DateTime 19 | name: bar 20 | default: '14-08-2007 01:30' 21 | year: 22 | list: [2007, 2008, 2009, 2010, 2011] 23 | -------------------------------------------------------------------------------- /t/elements/datetime_interval.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - type: DateTime 4 | name: foo 5 | field_order: ['day', 'month', 'year', 'hour', 'minute', 'second'] 6 | year: 7 | list: [2007, 2008, 2009, 2010, 2011] 8 | minute: 9 | interval: 5 10 | second: 11 | interval: 30 12 | -------------------------------------------------------------------------------- /t/elements/datetime_seconds.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - type: DateTime 4 | name: foo 5 | strftime: '%d/%m/%Y %H:%M:%S' 6 | field_order: ['day', 'month', 'year', 'hour', 'minute', 'second'] 7 | year: 8 | list: [2007, 2008, 2009, 2010, 2011] 9 | auto_inflate: 1 10 | -------------------------------------------------------------------------------- /t/elements/element_setup.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use lib 't/lib'; 7 | use HTML::FormFu; 8 | 9 | $::name = undef; 10 | 11 | my $form = HTML::FormFu->new( { auto_fieldset => 1, } ); 12 | 13 | $form->element( 14 | { type => '+HTMLFormFu::ElementSetup', 15 | name => 'xxx', 16 | } ); 17 | 18 | is( $::name, 'xxx', 'setup ran and had access to $self->name' ); 19 | -------------------------------------------------------------------------------- /t/elements/email.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 4; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | ok( my $element = $form->element('Email')->name('foo') ); 12 | 13 | my $expected_field_xhtml = qq{
14 | 15 |
}; 16 | 17 | is( "$element", $expected_field_xhtml ); 18 | 19 | # Valid 20 | { 21 | $form->process( { foo => 'test@example.com', } ); 22 | 23 | ok( $form->valid('foo'), 'foo valid' ); 24 | } 25 | 26 | # Invalid 27 | { 28 | $form->process( { foo => 'example.com', } ); 29 | 30 | ok( !$form->valid('foo'), 'foo invalid' ); 31 | } 32 | -------------------------------------------------------------------------------- /t/elements/error_attributes_failing_test.select-with-attrs.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - type: Select 4 | name: foo 5 | error_attributes: 6 | class: 'class-error_attributes' 7 | options: 8 | - [1, One] 9 | - [2, Two] 10 | constraints: 11 | - type: AutoSet 12 | message: 'test' 13 | -------------------------------------------------------------------------------- /t/elements/error_attributes_failing_test.select.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - type: Select 4 | name: foo 5 | options: 6 | - [1, One] 7 | - [2, Two] 8 | constraints: 9 | - type: AutoSet 10 | message: 'test' 11 | -------------------------------------------------------------------------------- /t/elements/error_attributes_failing_test.text-with-attrs.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - type: Text 4 | name: foo 5 | label: Foo 6 | error_attributes: 7 | class: 'class-error_attributes' 8 | constraints: 9 | - type: MaxLength 10 | max: 3 11 | message: 'test' 12 | -------------------------------------------------------------------------------- /t/elements/error_attributes_failing_test.text.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - type: Text 4 | name: foo 5 | label: Foo 6 | error_attributes: 7 | class: 'class-error_attributes' 8 | constraints: 9 | - type: MaxLength 10 | max: 3 11 | message: 'test' 12 | -------------------------------------------------------------------------------- /t/elements/field_default_empty_value.yml: -------------------------------------------------------------------------------- 1 | --- 2 | default_args: 3 | elements: 4 | Field: 5 | default_empty_value: 1 6 | 7 | elements: 8 | - name: f1 9 | - name: f2 10 | 11 | - type: Block 12 | nested_name: nested 13 | elements: 14 | - name: g1 15 | - name: g2 16 | 17 | - name: count 18 | type: Hidden 19 | 20 | - type: Repeatable 21 | nested_name: rep 22 | counter_name: count 23 | increment_field_names: 1 24 | elements: 25 | - name: h1 26 | - name: h2 27 | -------------------------------------------------------------------------------- /t/elements/field_non_param.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 6; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->element('Text')->name('foo'); 11 | $form->element('Submit')->name('submit')->non_param(1); 12 | 13 | # Required constraint not affected by non_param() 14 | $form->constraints('Required'); 15 | 16 | # indicator not affected by non_param() 17 | $form->indicator('submit'); 18 | 19 | $form->process( 20 | { foo => 1, 21 | submit => 'Submit', 22 | } ); 23 | 24 | is( $form->param('foo'), 1 ); 25 | ok( !$form->param('submit') ); 26 | 27 | is_deeply( [ $form->valid ], ['foo'] ); 28 | 29 | ok( $form->valid('foo') ); 30 | ok( !$form->valid('submit') ); 31 | 32 | is_deeply( $form->params, { foo => 1, } ); 33 | 34 | -------------------------------------------------------------------------------- /t/elements/fieldset_legend_attrs.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | my $outer = $form->load_config_file('t/elements/fieldset_legend_attrs.yml'); 12 | 13 | my $form_xhtml = < 15 |
16 | The Legend! 17 | The Content! 18 |
19 | 20 | EOF 21 | 22 | is( "$form", $form_xhtml ); 23 | 24 | -------------------------------------------------------------------------------- /t/elements/fieldset_legend_attrs.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - type: Fieldset 4 | legend: 'The Legend!' 5 | legend_attrs: 6 | class: my_legend 7 | content: 'The Content!' 8 | -------------------------------------------------------------------------------- /t/elements/file.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | my $element = $form->element('File')->name('foo'); 12 | 13 | my $field_xhtml = qq{
14 | 15 |
}; 16 | 17 | is( "$element", $field_xhtml ); 18 | 19 | my $form_xhtml = < 21 | $field_xhtml 22 | 23 | EOF 24 | 25 | is( "$form", $form_xhtml ); 26 | 27 | -------------------------------------------------------------------------------- /t/elements/file_post.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FormFu/HTML-FormFu/17eb6f1fb450dbd339efed9e4f6b6d53a5d35638/t/elements/file_post.txt -------------------------------------------------------------------------------- /t/elements/hidden.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | my $field = $form->element('Hidden')->name('foo'); 12 | 13 | my $field_xhtml = qq{}; 14 | 15 | is( "$field", $field_xhtml ); 16 | 17 | my $form_xhtml = < 19 | $field_xhtml 20 | 21 | EOF 22 | 23 | is( "$form", $form_xhtml ); 24 | 25 | -------------------------------------------------------------------------------- /t/elements/hr.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | # force a submission 12 | $form->indicator( sub {1} ); 13 | 14 | my $hr = $form->element('Hr'); 15 | 16 | $form->process( {} ); 17 | 18 | my $hr_xhtml = qq{
}; 19 | 20 | is( "$hr", $hr_xhtml ); 21 | 22 | -------------------------------------------------------------------------------- /t/elements/label.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use HTML::FormFu; 5 | use Test::More tests => 3; 6 | 7 | my $form = HTML::FormFu->new( 8 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 9 | 10 | $form->load_config_file('t/elements/label.yml'); 11 | 12 | $form->process; 13 | 14 | like( $form->get_field('foo'), qr/<\/span>/, "element found" ); 15 | 16 | like( 17 | $form->get_field('foo3'), 18 | qr/
bar<\/div>/, 19 | "element with value and different tag found" 20 | ); 21 | 22 | $form->process( { submit => 'Submit Value', } ); 23 | 24 | like( 25 | $form->get_field('foo3'), 26 | qr/
bar<\/div>/, 27 | "label retain_default works" 28 | ); 29 | -------------------------------------------------------------------------------- /t/elements/label.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - type: Label 4 | name: foo 5 | 6 | - type: Label 7 | name: foo3 8 | default: bar 9 | retain_default: 1 10 | tag: div 11 | 12 | - type: Submit 13 | name: submit 14 | -------------------------------------------------------------------------------- /t/elements/label_value_submission.yml: -------------------------------------------------------------------------------- 1 | --- 2 | auto_fieldset: 1 3 | 4 | elements: 5 | - type: Hidden 6 | name: id 7 | 8 | - type: Label 9 | name: name 10 | 11 | - type: Hidden 12 | name: name 13 | 14 | - type: Submit 15 | name: submit 16 | -------------------------------------------------------------------------------- /t/elements/no_block_tag.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | $form->load_config_file('t/elements/no_block_tag.yml'); 12 | 13 | my $expected_form_xhtml = < 15 | 16 |
17 | 18 |
19 | 20 | 21 | EOF 22 | 23 | is( "$form", $expected_form_xhtml ); 24 | -------------------------------------------------------------------------------- /t/elements/no_block_tag.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - type: Block 4 | tag: ~ 5 | elements: 6 | - name: foo 7 | -------------------------------------------------------------------------------- /t/elements/no_container_tag.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | $form->load_config_file('t/elements/no_container_tag.yml'); 12 | 13 | my $expected_form_xhtml = < 15 | 16 | 17 | EOF 18 | 19 | is( "$form", $expected_form_xhtml ); 20 | -------------------------------------------------------------------------------- /t/elements/no_container_tag.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | name: foo 4 | container_tag: ~ 5 | -------------------------------------------------------------------------------- /t/elements/number.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - type: Number 4 | name: foo 5 | constraints: 6 | - Number 7 | -------------------------------------------------------------------------------- /t/elements/object/field_layout_field_custom: -------------------------------------------------------------------------------- 1 | [% INCLUDE field_layout_field %][% IF self.object.get_constraint({type => 'Required'}) %] **[% END %] -------------------------------------------------------------------------------- /t/elements/password.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 3; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | my $field = $form->element('Password')->name('foo'); 12 | 13 | my $field_xhtml = qq{
14 | 15 |
}; 16 | 17 | is( "$field", $field_xhtml, 'stringified field' ); 18 | 19 | my $form_xhtml = < 21 | $field_xhtml 22 | 23 | EOF 24 | 25 | is( "$form", $form_xhtml, 'stringified form' ); 26 | 27 | # With mocked basic query 28 | { 29 | $form->process( { foo => 'yada', } ); 30 | 31 | like( $form->get_field('foo'), qr/value=""/ ); 32 | } 33 | -------------------------------------------------------------------------------- /t/elements/password_render_value.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | $form->element('Password')->name('foo')->render_value(1); 12 | 13 | my $field_xhtml = qq{
14 | 15 |
}; 16 | 17 | is( $form->get_field('foo'), $field_xhtml ); 18 | 19 | # With mocked basic query 20 | { 21 | $form->process( { foo => 'yada', } ); 22 | 23 | my $field_xhtml = qq{
24 | 25 |
}; 26 | 27 | is( $form->get_field('foo'), $field_xhtml ); 28 | } 29 | -------------------------------------------------------------------------------- /t/elements/radiogroup_attributes_escaped.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | $form->load_config_file('t/elements/radiogroup_attributes_escaped.yml'); 12 | $form->process; 13 | 14 | my $field = $form->get_field('foo'); 15 | 16 | my $html = qq{
17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
}; 28 | 29 | is( "$field", $html ); 30 | -------------------------------------------------------------------------------- /t/elements/radiogroup_attributes_escaped.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - type: Radiogroup 4 | name: foo 5 | options: 6 | - value: 1 7 | label: 'First' 8 | attributes: 9 | myattr: 'escape&attr' 10 | label_attributes: 11 | myattr: 'escape&label' 12 | container_attributes: 13 | myattr: 'escape&container' 14 | 15 | - value: 2 16 | label: 'Second' 17 | attributes_xml: 18 | myattr: 'noescape&' 19 | -------------------------------------------------------------------------------- /t/elements/radiogroup_attrs_xml.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | my $field = $form->element('Radiogroup')->name('foo')->options( [ 12 | { label => 'One', 13 | attrs => { class => 'foo' }, 14 | attrs_xml => { onsubmit => '' }, 15 | } ] ); 16 | 17 | is( "$form", < 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | EOF 29 | -------------------------------------------------------------------------------- /t/elements/radiogroup_dup_opt.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | # dies 11 | 12 | eval { 13 | $form->element('Radiogroup')->name('foo')->options( [ 14 | { label => 'fu', 15 | value => '1', 16 | attributes => { foo => 1 }, 17 | attrs => { bar => 2 }, 18 | } ] ); 19 | }; 20 | 21 | ok($@); 22 | -------------------------------------------------------------------------------- /t/elements/radiogroup_id.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | use lib 't/lib'; 8 | use HTMLFormFu::TestLib; 9 | 10 | my $form = HTML::FormFu->new( 11 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 12 | 13 | $form->id('form')->auto_id('%n%c'); 14 | 15 | my $foo = $form->element('Radiogroup')->name('foo')->values( [ 1, 2 ] ); 16 | 17 | my $foo_xhtml = qq{
18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 |
}; 29 | 30 | is( "$foo", $foo_xhtml ); 31 | 32 | -------------------------------------------------------------------------------- /t/elements/radiogroup_unknown_opt.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | # dies 11 | 12 | eval { 13 | $form->element('Radiogroup')->name('foo')->options( [ 14 | { label => 'fu', 15 | value => '1', 16 | unknown => 'dies', 17 | } ] ); 18 | }; 19 | 20 | ok($@); 21 | -------------------------------------------------------------------------------- /t/elements/repeatable_counter_name.yml: -------------------------------------------------------------------------------- 1 | --- 2 | auto_fieldset: 1 3 | 4 | elements: 5 | - type: Repeatable 6 | increment_field_names: 1 7 | counter_name: count 8 | elements: 9 | - name: foo 10 | - name: bar 11 | - type: Submit 12 | name: submit 13 | -------------------------------------------------------------------------------- /t/elements/repeatable_repeatable.yml: -------------------------------------------------------------------------------- 1 | --- 2 | auto_fieldset: 1 3 | 4 | elements: 5 | - type: Hidden 6 | name: count 7 | 8 | - type: Repeatable 9 | counter_name: count 10 | elements: 11 | - name: foo 12 | 13 | - type: Hidden 14 | name: count 15 | 16 | - type: Repeatable 17 | counter_name: count 18 | 19 | elements: 20 | - name: foo 21 | - name: bar 22 | -------------------------------------------------------------------------------- /t/elements/reset.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | my $field = $form->element('Reset')->name('foo'); 12 | 13 | my $field_xhtml = qq{
14 | 15 |
}; 16 | 17 | is( "$field", $field_xhtml, 'stringified field' ); 18 | 19 | my $form_xhtml = < 21 | $field_xhtml 22 | 23 | EOF 24 | 25 | is( "$form", $form_xhtml, 'stringified form' ); 26 | 27 | -------------------------------------------------------------------------------- /t/elements/select_attributes_escaped.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | $form->load_config_file('t/elements/select_attributes_escaped.yml'); 12 | $form->process; 13 | 14 | my $field = $form->get_field('foo'); 15 | 16 | my $html = qq{
17 | 21 |
}; 22 | 23 | is( "$field", $html ); 24 | -------------------------------------------------------------------------------- /t/elements/select_attributes_escaped.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - type: Select 4 | name: foo 5 | options: 6 | - value: 1 7 | label: 'First' 8 | attributes: 9 | myattr: 'escape&attr' 10 | 11 | - value: 2 12 | label: 'Second' 13 | attributes_xml: 14 | myattr: 'noescape&' 15 | -------------------------------------------------------------------------------- /t/elements/select_empty_first.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | $form->load_config_file('t/elements/select_empty_first.yml'); 12 | 13 | $form->process; 14 | 15 | is( "$form", < 17 |
18 | 23 |
24 | 25 | EOF 26 | -------------------------------------------------------------------------------- /t/elements/select_empty_first.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - type: Select 4 | name: foo 5 | empty_first: 1 6 | options: 7 | - [1, One] 8 | - [2, Two] 9 | -------------------------------------------------------------------------------- /t/elements/select_label_loc.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use lib 't/lib'; 4 | 5 | use Test::More tests => 1; 6 | 7 | use HTML::FormFu; 8 | 9 | my $form = HTML::FormFu->new( 10 | { localize_class => 'HTMLFormFu::I18N', 11 | tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' }, 12 | } ); 13 | 14 | { 15 | my $field = $form->element('Select')->name('foo'); 16 | $field->options( [ 17 | { label_loc => 'label_foo', 18 | value => 'foo', 19 | } ] ); 20 | 21 | my $field_xhtml = qq{
22 | 25 |
}; 26 | 27 | is( "$field", $field_xhtml, 'stringified field' ); 28 | 29 | } 30 | -------------------------------------------------------------------------------- /t/elements/select_multi_default_values.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | my $field = $form->element('Select')->name('foo') 12 | ->options( [ [ 1 => 'One' ], [ 2 => 'Two' ], [ 3 => 'Three' ] ] ); 13 | 14 | $form->default_values( { foo => [ 2, 3 ] } ); 15 | 16 | # correct options are rendered selected 17 | { 18 | $form->process; 19 | 20 | like( "$form", qr/value="2" selected="selected"/ ); 21 | like( "$form", qr/value="3" selected="selected"/ ); 22 | } 23 | -------------------------------------------------------------------------------- /t/elements/select_same_name.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | $form->load_config_file('t/elements/select_same_name.yml'); 12 | 13 | $form->process( { foo => [ 1, 2 ], } ); 14 | 15 | is( "$form", < 17 |
18 | 22 |
23 |
24 | 28 |
29 | 30 | EOF 31 | -------------------------------------------------------------------------------- /t/elements/select_same_name.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - type: Select 4 | name: foo 5 | options: 6 | - [1, One] 7 | - [2, Two] 8 | 9 | - type: Select 10 | name: foo 11 | options: 12 | - [1, One] 13 | - [2, Two] 14 | -------------------------------------------------------------------------------- /t/elements/simple_table.yml: -------------------------------------------------------------------------------- 1 | --- 2 | auto_fieldset: 1 3 | elements: 4 | - type: SimpleTable 5 | headers: 6 | - foo 7 | - bar 8 | rows: 9 | - 10 | - type: Text 11 | name: foo 12 | - type: Text 13 | name: bar 14 | - 15 | - type: Radio 16 | name: foo 17 | - type: Radio 18 | name: bar 19 | -------------------------------------------------------------------------------- /t/elements/simple_table_class.yml: -------------------------------------------------------------------------------- 1 | --- 2 | auto_fieldset: 1 3 | elements: 4 | - type: SimpleTable 5 | odd_class: x 6 | even_class: y 7 | headers: 8 | - foo 9 | rows: 10 | - 11 | - type: Text 12 | name: foo 13 | - 14 | - type: Text 15 | name: bar 16 | - 17 | - type: Text 18 | name: baz 19 | -------------------------------------------------------------------------------- /t/elements/simple_table_multiple.yml: -------------------------------------------------------------------------------- 1 | --- 2 | auto_fieldset: 1 3 | elements: 4 | - type: SimpleTable 5 | headers: 6 | - foo 7 | - bar 8 | rows: 9 | - 10 | - 11 | - type: Text 12 | name: foo 13 | - type: Radio 14 | name: foo 15 | - 16 | - type: Text 17 | name: bar 18 | - type: Radio 19 | name: bar 20 | -------------------------------------------------------------------------------- /t/elements/src.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | $form->auto_fieldset(1); 12 | 13 | my $block = $form->element( 14 | { type => 'Src', 15 | content_xml => 'Hello World!', 16 | } ); 17 | 18 | my $block_xhtml = qq{ 19 | Hello World! 20 | }; 21 | 22 | is( $block, $block_xhtml ); 23 | 24 | my $form_xhtml = < 26 |
27 | $block_xhtml 28 |
29 | 30 | EOF 31 | 32 | is( $form, $form_xhtml ); 33 | 34 | -------------------------------------------------------------------------------- /t/elements/submit.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | my $field = $form->element('Submit')->name('foo'); 12 | 13 | my $field_xhtml = qq{
14 | 15 |
}; 16 | 17 | is( "$field", $field_xhtml, 'stringified field' ); 18 | 19 | my $form_xhtml = < 21 | $field_xhtml 22 | 23 | EOF 24 | 25 | is( "$form", $form_xhtml, 'stringified form' ); 26 | 27 | -------------------------------------------------------------------------------- /t/elements/text_auto_comment_class.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | $form->load_config_file('t/elements/text_auto_comment_class.yml'); 12 | 13 | my $expected_form_xhtml = < 15 |
16 |
17 | 18 | 19 | Foo! 20 | 21 |
22 |
23 | 24 | 25 | Bar! 26 | 27 |
28 |
29 | 30 | EOF 31 | 32 | is( "$form", $expected_form_xhtml ); 33 | -------------------------------------------------------------------------------- /t/elements/text_auto_comment_class.yml: -------------------------------------------------------------------------------- 1 | --- 2 | auto_fieldset: 1 3 | elements: 4 | - name: foo 5 | comment: 'Foo!' 6 | 7 | - name: bar 8 | comment: 'Bar!' 9 | auto_comment_class: 'formfu_%n_comment' 10 | -------------------------------------------------------------------------------- /t/elements/text_auto_container_class.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | $form->load_config_file('t/elements/text_auto_container_class.yml'); 12 | 13 | my $expected_form_xhtml = < 15 |
16 |
17 | 18 |
19 |
20 | 21 |
22 |
23 | 24 | EOF 25 | 26 | is( "$form", $expected_form_xhtml ); 27 | -------------------------------------------------------------------------------- /t/elements/text_auto_container_class.yml: -------------------------------------------------------------------------------- 1 | --- 2 | auto_fieldset: 1 3 | elements: 4 | - name: foo 5 | 6 | - name: bar 7 | auto_container_class: 'formfu_%n_%t' 8 | -------------------------------------------------------------------------------- /t/elements/text_auto_container_comment_class.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | $form->load_config_file('t/elements/text_auto_container_comment_class.yml'); 12 | 13 | my $expected_form_xhtml = < 15 |
16 |
17 | 18 | 19 | Foo! 20 | 21 |
22 |
23 | 24 | 25 | Bar! 26 | 27 |
28 |
29 | 30 | EOF 31 | 32 | is( "$form", $expected_form_xhtml ); 33 | -------------------------------------------------------------------------------- /t/elements/text_auto_container_comment_class.yml: -------------------------------------------------------------------------------- 1 | --- 2 | auto_fieldset: 1 3 | elements: 4 | - name: foo 5 | comment: 'Foo!' 6 | 7 | - name: bar 8 | comment: 'Bar!' 9 | auto_container_comment_class: 'formfu_%n_comment' 10 | -------------------------------------------------------------------------------- /t/elements/text_auto_container_error_class.yml: -------------------------------------------------------------------------------- 1 | --- 2 | auto_fieldset: 1 3 | elements: 4 | - name: foo 5 | constraint: 6 | - Required 7 | 8 | - name: bar 9 | auto_container_error_class: 'formfu_error' 10 | constraint: 11 | - Required 12 | 13 | - type: Submit 14 | name: submit 15 | -------------------------------------------------------------------------------- /t/elements/text_auto_container_label_class.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | $form->load_config_file('t/elements/text_auto_container_label_class.yml'); 12 | 13 | my $expected_form_xhtml = < 15 |
16 |
17 | 18 | 19 |
20 |
21 | 22 | 23 |
24 |
25 | 26 | EOF 27 | 28 | is( "$form", $expected_form_xhtml ); 29 | -------------------------------------------------------------------------------- /t/elements/text_auto_container_label_class.yml: -------------------------------------------------------------------------------- 1 | --- 2 | auto_fieldset: 1 3 | auto_label: '%n' 4 | elements: 5 | - name: foo 6 | 7 | - name: bar 8 | auto_container_label_class: '%t_label' 9 | -------------------------------------------------------------------------------- /t/elements/text_auto_label_class.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | $form->load_config_file('t/elements/text_auto_label_class.yml'); 12 | 13 | my $expected_form_xhtml = < 15 |
16 |
17 | 18 | 19 |
20 |
21 | 22 | 23 |
24 |
25 | 26 | EOF 27 | 28 | is( "$form", $expected_form_xhtml ); 29 | -------------------------------------------------------------------------------- /t/elements/text_auto_label_class.yml: -------------------------------------------------------------------------------- 1 | --- 2 | auto_fieldset: 1 3 | auto_label: '%n' 4 | elements: 5 | - name: foo 6 | 7 | - name: bar 8 | auto_label_class: '%t_label' 9 | -------------------------------------------------------------------------------- /t/elements/text_datalist_options.yml: -------------------------------------------------------------------------------- 1 | --- 2 | id: form 3 | auto_id: '%f_%n' 4 | auto_datalist_id: '%f_%n_datalist' 5 | 6 | elements: 7 | - type: Text 8 | name: foo 9 | datalist_options: 10 | - [ one, One ] 11 | - [ two, Two ] 12 | - value: three 13 | label_loc: test_label 14 | - value_xml: '>four' 15 | label: Four 16 | -------------------------------------------------------------------------------- /t/elements/text_datalist_values.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' }, } ); 10 | 11 | $form->load_config_file('t/elements/text_datalist_values.yml'); 12 | 13 | my $expected_form_xhtml = < 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | EOF 25 | 26 | is( "$form", $expected_form_xhtml ); 27 | -------------------------------------------------------------------------------- /t/elements/text_datalist_values.yml: -------------------------------------------------------------------------------- 1 | --- 2 | id: form 3 | auto_id: '%f_%n' 4 | auto_datalist_id: '%f_%n_datalist' 5 | 6 | elements: 7 | - type: Text 8 | name: foo 9 | datalist_values: 10 | - one 11 | - two 12 | - three 13 | -------------------------------------------------------------------------------- /t/elements/text_errors.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | my $foo = $form->element('Text')->name('foo')->label('My Foo'); 12 | my $bar = $form->element('Text')->name('bar'); 13 | 14 | $form->constraint( Number => 'foo' ); 15 | $form->constraint( Word => 'bar' ); 16 | $form->constraint( Required => 'foo', 'bar' ); 17 | 18 | my $foo_xhtml = qq{
19 | 20 | 21 |
}; 22 | 23 | is( "$foo", $foo_xhtml ); 24 | 25 | my $bar_xhtml = qq{
26 | 27 |
}; 28 | 29 | is( "$bar", $bar_xhtml ); 30 | -------------------------------------------------------------------------------- /t/elements/text_layout.yml: -------------------------------------------------------------------------------- 1 | --- 2 | id: form 3 | 4 | elements: 5 | - name: foo 6 | label: Foo 7 | comment: The foo 8 | auto_id: '%f_%n' 9 | -------------------------------------------------------------------------------- /t/elements/text_title.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use lib 't/lib'; 4 | 5 | use Test::More tests => 1; 6 | 7 | use HTML::FormFu; 8 | 9 | my $form = HTML::FormFu->new( 10 | { localize_class => 'HTMLFormFu::I18N', 11 | tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' }, 12 | } ); 13 | 14 | $form->element('Text')->name('foo')->title('The Foo'); 15 | $form->element('Text')->name('bar')->title_loc('bar_title'); 16 | 17 | my $expected_form_xhtml = < 19 |
20 | 21 |
22 |
23 | 24 |
25 | 26 | EOF 27 | 28 | is( "$form", $expected_form_xhtml ); 29 | -------------------------------------------------------------------------------- /t/elements/url.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - type: URL 4 | name: foo 5 | title: "Only http and https URLs allowed" 6 | -------------------------------------------------------------------------------- /t/field_accessor_loc.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use lib 't/lib'; 7 | use HTML::FormFu; 8 | 9 | my $form = HTML::FormFu->new( 10 | { localize_class => 'HTMLFormFu::I18N', 11 | tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' }, 12 | } ); 13 | 14 | $form->element('Text')->name('foo')->label_loc('test_label') 15 | ->comment_loc('test_comment')->default_loc('test_default_value'); 16 | 17 | my $xhtml = qq{
18 | 19 | 20 | 21 | My Comment 22 | 23 |
}; 24 | 25 | is( $form->get_field('foo'), $xhtml ); 26 | -------------------------------------------------------------------------------- /t/field_accessor_loc_arrayref.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use lib 't/lib'; 7 | use HTML::FormFu; 8 | 9 | my $form = HTML::FormFu->new( 10 | { localize_class => 'HTMLFormFu::I18N', 11 | tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' }, 12 | } ); 13 | 14 | $form->load_config_file('t/field_accessor_loc_arrayref.yml'); 15 | 16 | like( $form->get_field('foo'), qr|\Q| ); 17 | -------------------------------------------------------------------------------- /t/field_accessor_loc_arrayref.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - name: foo 4 | label_loc: 5 | - test_two_args 6 | - one 7 | - two 8 | -------------------------------------------------------------------------------- /t/field_change_name.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->element('Text')->name('foo')->constraint('Required'); 11 | 12 | ok( $form->get_constraint('foo') ); 13 | 14 | $form->get_field('foo')->name('bar'); 15 | 16 | ok( $form->get_constraint('bar') ); 17 | -------------------------------------------------------------------------------- /t/filters/compoundjoin.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 3; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | $form->load_config_file('t/filters/compoundjoin.yml'); 12 | 13 | $form->process; 14 | 15 | $form->process( 16 | { 'rep_1.address.number' => '10', 17 | 'rep_1.address.street' => 'Downing Street', 18 | } ); 19 | 20 | ok( $form->submitted_and_valid ); 21 | 22 | is( $form->param_value('rep_1.address'), '10 Downing Street' ); 23 | 24 | is_deeply( $form->params, { rep_1 => { address => '10 Downing Street' }, }, ); 25 | -------------------------------------------------------------------------------- /t/filters/compoundjoin.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | elements: 4 | - type: Repeatable 5 | nested_name: rep 6 | 7 | elements: 8 | - type: Multi 9 | name: address 10 | 11 | elements: 12 | - name: number 13 | - name: street 14 | 15 | filters: 16 | type: CompoundJoin 17 | -------------------------------------------------------------------------------- /t/filters/compoundjoin_field_order.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->load_config_file('t/filters/compoundjoin_field_order.yml'); 11 | 12 | $form->process( 13 | { 'address.street' => 'Downing Street', 14 | 'address.number' => '10', 15 | } ); 16 | 17 | ok( $form->submitted_and_valid ); 18 | 19 | is( $form->param_value('address'), '10 Downing Street' ); 20 | -------------------------------------------------------------------------------- /t/filters/compoundjoin_field_order.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | elements: 4 | - type: Multi 5 | name: address 6 | 7 | elements: 8 | - name: street 9 | - name: number 10 | 11 | filters: 12 | type: CompoundJoin 13 | field_order: 14 | - number 15 | - street 16 | -------------------------------------------------------------------------------- /t/filters/compoundjoin_join.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->load_config_file('t/filters/compoundjoin_join.yml'); 11 | 12 | $form->process( 13 | { 'sortcode.p1' => '01', 14 | 'sortcode.p2' => '02', 15 | 'sortcode.p3' => '03', 16 | } ); 17 | 18 | ok( $form->submitted_and_valid ); 19 | 20 | is( $form->param_value('sortcode'), '01-02-03' ); 21 | -------------------------------------------------------------------------------- /t/filters/compoundjoin_join.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | elements: 4 | - type: Multi 5 | name: sortcode 6 | 7 | elements: 8 | - name: p1 9 | - name: p2 10 | - name: p3 11 | 12 | 13 | filters: 14 | type: CompoundJoin 15 | join: '-' 16 | -------------------------------------------------------------------------------- /t/filters/compoundsprintf.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 3; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->load_config_file('t/filters/compoundsprintf.yml'); 11 | 12 | $form->process( 13 | { 'date.day' => '26', 14 | 'date.month' => '6', 15 | 'date.year' => '2008', 16 | } ); 17 | 18 | ok( $form->submitted_and_valid ); 19 | 20 | is( $form->param_value('date'), '26-06-2008' ); 21 | 22 | is_deeply( $form->params, { date => '26-06-2008', }, ); 23 | -------------------------------------------------------------------------------- /t/filters/compoundsprintf.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | elements: 4 | - type: Multi 5 | name: date 6 | 7 | elements: 8 | - name: day 9 | - name: month 10 | - name: year 11 | 12 | filters: 13 | type: CompoundSprintf 14 | sprintf: '%02d-%02d-%04d' 15 | -------------------------------------------------------------------------------- /t/filters/compoundsprintf_field_order.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 3; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->load_config_file('t/filters/compoundsprintf_field_order.yml'); 11 | 12 | $form->process( 13 | { 'date.month' => '6', 14 | 'date.day' => '26', 15 | 'date.year' => '2008', 16 | } ); 17 | 18 | ok( $form->submitted_and_valid ); 19 | 20 | is( $form->param_value('date'), '26-06-2008' ); 21 | 22 | is_deeply( $form->params, { date => '26-06-2008', }, ); 23 | -------------------------------------------------------------------------------- /t/filters/compoundsprintf_field_order.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | elements: 4 | - type: Multi 5 | name: date 6 | 7 | elements: 8 | - name: month 9 | - name: day 10 | - name: year 11 | 12 | filters: 13 | type: CompoundSprintf 14 | sprintf: '%02d-%02d-%04d' 15 | field_order: 16 | - day 17 | - month 18 | - year 19 | -------------------------------------------------------------------------------- /t/filters/encode.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use Encode; 4 | 5 | use Test::More tests => 2; 6 | 7 | use HTML::FormFu; 8 | 9 | my $form = HTML::FormFu->new; 10 | 11 | $form->element('Text')->name('foo')->filter('Encode') 12 | ->candidates(qw(euc-jp sjis jis))->encode_to('euc-jp'); 13 | 14 | my $utf8_foo 15 | = decode_utf8('エイチティーエムエル::フォームフー'); 16 | my $original_foo = encode( 'sjis', $utf8_foo ); 17 | my $filtered_foo = encode( 'euc-jp', $utf8_foo ); 18 | 19 | $form->process( { foo => $original_foo, } ); 20 | 21 | # foo is filtered 22 | is( decode( 'euc-jp', $form->param('foo') ), $utf8_foo, 'foo filtered' ); 23 | is( decode( 'euc-jp', $form->params->{foo} ), $utf8_foo, 'foo filtered' ); 24 | -------------------------------------------------------------------------------- /t/filters/formatnumber.yml: -------------------------------------------------------------------------------- 1 | --- 2 | locale: de_DE 3 | 4 | elements: 5 | - name: foo 6 | filters: 7 | - type: FormatNumber 8 | -------------------------------------------------------------------------------- /t/filters/htmlescape.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->element('Text')->name('foo')->filter('HTMLEscape'); 11 | 12 | my $original_foo = qq{&escape "this"}; 13 | my $filtered_foo = "&escape "this""; 14 | 15 | $form->process( { foo => $original_foo, } ); 16 | 17 | # foo is filtered 18 | is( $form->param('foo'), $filtered_foo, 'foo filtered' ); 19 | is( $form->params->{foo}, $filtered_foo, 'foo filtered' ); 20 | 21 | -------------------------------------------------------------------------------- /t/filters/lowercase.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->element('Text')->name('foo')->filter('LowerCase'); 11 | 12 | my $original_foo = "Foo Bar"; 13 | my $filtered_foo = "foo bar"; 14 | 15 | $form->process( { foo => $original_foo, } ); 16 | 17 | # foo is filtered 18 | is( $form->param('foo'), $filtered_foo, 'foo filtered' ); 19 | is( $form->params->{foo}, $filtered_foo, 'foo filtered' ); 20 | 21 | -------------------------------------------------------------------------------- /t/filters/nonnumeric.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->element('Text')->name('foo')->filter('NonNumeric'); 11 | 12 | my $original_foo = " 0123-4567 (8a9)"; 13 | my $filtered_foo = "0123456789"; 14 | 15 | $form->process( { foo => $original_foo, } ); 16 | 17 | # foo is filtered 18 | is( $form->param('foo'), $filtered_foo, 'foo filtered' ); 19 | is( $form->params->{foo}, $filtered_foo, 'foo filtered' ); 20 | 21 | -------------------------------------------------------------------------------- /t/filters/regex.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - name: foo 4 | filters: 5 | - type: Regex 6 | match: !!perl/regexp (?-xism:\A\s+|\s+\z) 7 | -------------------------------------------------------------------------------- /t/filters/regex_eval.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 4; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->load_config_file('t/filters/regex_eval.yml'); 11 | 12 | { 13 | $form->process( { foo => '.4.5 ', } ); 14 | 15 | is( $form->param_value('foo'), '4.5' ); 16 | } 17 | 18 | { 19 | $form->process( { foo => '4.', } ); 20 | 21 | is( $form->param_value('foo'), '4' ); 22 | } 23 | 24 | { 25 | $form->process( { foo => '4.0', } ); 26 | 27 | is( $form->param_value('foo'), '4.0' ); 28 | } 29 | 30 | # doesn't filter, as it doesn't match the regex 31 | { 32 | $form->process( { foo => ' a', } ); 33 | 34 | is( $form->param_value('foo'), ' a' ); 35 | } 36 | -------------------------------------------------------------------------------- /t/filters/regex_eval.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - name: foo 4 | filters: 5 | - type: Regex 6 | match: '\A.*?([0-9]+(?:\.[0-9]+)?).*\z' 7 | replace: '$1' 8 | eval: 1 9 | -------------------------------------------------------------------------------- /t/filters/split.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 4; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->load_config_file('t/filters/split.yml'); 11 | 12 | $form->process( 13 | { foo => 'FOO', 14 | bar => '1-2-3', 15 | } ); 16 | 17 | is_deeply( $form->param_array('foo'), [ 'F', 'O', 'O' ] ); 18 | 19 | is( $form->param_value('foo'), 'F' ); 20 | 21 | is_deeply( $form->param_array('bar'), [ 1, '2-3' ] ); 22 | 23 | is( $form->param_value('bar'), 1 ); 24 | -------------------------------------------------------------------------------- /t/filters/split.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - name: foo 4 | filters: 5 | - type: Split 6 | 7 | - name: bar 8 | filters: 9 | - type: Split 10 | regex: '-' 11 | limit: 2 12 | -------------------------------------------------------------------------------- /t/filters/trimedges.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | $form->element('Text')->name('foo')->filter('TrimEdges'); 12 | 13 | my $original_foo = " Foo Bar "; 14 | my $filtered_foo = "Foo Bar"; 15 | 16 | $form->process( { foo => $original_foo } ); 17 | 18 | # foo is filtered 19 | is( $form->params->{foo}, $filtered_foo ); 20 | 21 | like( $form->get_field('foo'), qr/$original_foo/ ); 22 | 23 | -------------------------------------------------------------------------------- /t/filters/uppercase.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->element('Text')->name('foo')->filter('UpperCase'); 11 | 12 | my $original_foo = "Foo Bar"; 13 | my $filtered_foo = "FOO BAR"; 14 | 15 | $form->process( { foo => $original_foo, } ); 16 | 17 | # foo is filtered 18 | is( $form->param('foo'), $filtered_foo, 'foo filtered' ); 19 | is( $form->params->{foo}, $filtered_foo, 'foo filtered' ); 20 | 21 | -------------------------------------------------------------------------------- /t/filters/whitespace.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->element('Text')->name('foo')->filter('Whitespace'); 11 | 12 | my $original_foo = "Foo Bar"; 13 | my $filtered_foo = "FooBar"; 14 | 15 | $form->process( { foo => $original_foo, } ); 16 | 17 | # foo is filtered 18 | is( $form->param('foo'), $filtered_foo, 'foo filtered' ); 19 | is( $form->params->{foo}, $filtered_foo, 'foo filtered' ); 20 | 21 | -------------------------------------------------------------------------------- /t/form/add_render_class_args.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->tt_args( { INCLUDE_PATH => ['root'], } ); 11 | 12 | $form->add_tt_args( { TEMPLATE_ALLOY => 1, } ); 13 | 14 | is_deeply( 15 | $form->tt_args, 16 | { INCLUDE_PATH => ['root'], 17 | TEMPLATE_ALLOY => 1, 18 | } ); 19 | 20 | -------------------------------------------------------------------------------- /t/form/add_valid_unknown.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->element('Text')->name('foo'); 11 | 12 | $form->process( { foo => 1, } ); 13 | 14 | is_deeply( $form->params, { foo => 1, } ); 15 | 16 | $form->add_valid( bar => 'b' ); 17 | 18 | is_deeply( 19 | $form->params, 20 | { foo => 1, 21 | bar => 'b', 22 | } ); 23 | 24 | -------------------------------------------------------------------------------- /t/form/auto_constraint_class.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | $form->id('form')->auto_constraint_class('%t_constraint'); 12 | 13 | $form->element('Text')->name('foo'); 14 | $form->element('Text')->name('bar')->auto_constraint_class('%f_%t_c'); 15 | 16 | $form->constraint('Number'); 17 | 18 | is( $form->get_field('foo'), 19 | q{
20 | 21 |
} 22 | ); 23 | 24 | is( $form->get_field('bar'), 25 | q{
26 | 27 |
} 28 | ); 29 | -------------------------------------------------------------------------------- /t/form/auto_error_class.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 3; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | $form->element('Text')->name('foo'); 12 | $form->element('Text')->name('bar')->auto_error_class('form_%t_%s_error'); 13 | 14 | $form->constraint('Number'); 15 | 16 | $form->process( 17 | { foo => 'a', 18 | bar => 'b', 19 | } ); 20 | 21 | unlike( $form->get_field('foo'), qr/error/ ); 22 | like( $form->get_field('foo'), qr/This field must be a number/i ); 23 | 24 | like( $form->get_field('bar'), 25 | qr!\Q! ); 26 | -------------------------------------------------------------------------------- /t/form/auto_error_field_class.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 3; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | $form->element('Text')->name('foo'); 12 | $form->element('Text')->name('bar')->auto_error_field_class('is-invalid'); 13 | 14 | $form->constraint('Number'); 15 | 16 | $form->process( 17 | { foo => 'a', 18 | bar => 'b', 19 | } ); 20 | 21 | unlike( $form->get_field('foo'), qr/error/ ); 22 | like( $form->get_field('foo'), qr/This field must be a number/i ); 23 | 24 | like( $form->get_field('bar'), qr!]+ class="is-invalid"! ); 25 | -------------------------------------------------------------------------------- /t/form/auto_error_message.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | $form->element('Text')->name('foo'); 12 | $form->element('Text')->name('bar') 13 | ->auto_error_message('form_constraint_integer'); 14 | 15 | $form->constraint('Number'); 16 | 17 | $form->process( 18 | { foo => 'a', 19 | bar => 'b', 20 | } ); 21 | 22 | like( $form->get_field('foo'), qr!This field must be a number! ); 23 | 24 | like( $form->get_field('bar'), qr/integer/i ); 25 | -------------------------------------------------------------------------------- /t/form/auto_label.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; 5 | 6 | use HTML::FormFu; 7 | use lib 't/lib'; 8 | 9 | my $form = HTML::FormFu->new( 10 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 11 | 12 | $form->localize_class('HTMLFormFu::I18N')->id('form')->auto_label('label_%n'); 13 | 14 | $form->element('Text')->name('foo'); 15 | $form->element('Text')->name('bar')->auto_label('label_%f_%n'); 16 | 17 | like( $form->get_field('foo'), qr!! ); 18 | 19 | like( $form->get_field('bar'), qr!! ); 20 | -------------------------------------------------------------------------------- /t/form/config_callback.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->config_callback( 11 | { plain_value => sub { 12 | return if !defined $_; 13 | s/Foo/Bar/; 14 | } 15 | } ); 16 | 17 | $form->load_config_file('t/form/config_callback.yml'); 18 | 19 | is( $form->get_field('foo')->label, 'Bar' ); 20 | -------------------------------------------------------------------------------- /t/form/config_callback.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - name: foo 4 | label: Foo 5 | -------------------------------------------------------------------------------- /t/form/constraints_from_dbic.yml: -------------------------------------------------------------------------------- 1 | --- 2 | constraints_from_dbic: 3 | - MyApp::Schema::Person 4 | - { dongle: 'MyApp::Schema::Dongle' } 5 | elements: 6 | - type: Fieldset 7 | elements: 8 | - name: title 9 | - name: name 10 | - name: age 11 | - name: dongle 12 | - name: is_human 13 | - name: income 14 | 15 | - type: Block 16 | nested_name: parent 17 | constraints_from_dbic: 'MyApp::Schema::Person' 18 | elements: 19 | - name: title 20 | - name: name 21 | - name: age 22 | -------------------------------------------------------------------------------- /t/form/default_args_alt.yml: -------------------------------------------------------------------------------- 1 | --- 2 | default_args: 3 | elements: 4 | Input: 5 | add_attrs: 6 | class: is_input 7 | 'Input|-Multi': 8 | add_attrs: 9 | class: not_in_multi 10 | 11 | elements: 12 | - name: foo 13 | 14 | - type: Multi 15 | name: multi 16 | elements: 17 | name: bar 18 | -------------------------------------------------------------------------------- /t/form/default_args_isa.yml: -------------------------------------------------------------------------------- 1 | --- 2 | auto_fieldset: 1 3 | 4 | default_args: 5 | elements: 6 | Block: 7 | attributes: 8 | class: does_block 9 | Field: 10 | comment: 'Does Field' 11 | Input: 12 | id: bar 13 | Multi: 14 | label: 'My Multi' 15 | 16 | 17 | elements: 18 | - type: Multi 19 | name: foo 20 | elements: 21 | name: bar 22 | -------------------------------------------------------------------------------- /t/form/default_values.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 3; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | $form->element('Text')->name('foo'); 12 | 13 | $form->element('Checkbox')->name('bar')->value('y'); 14 | 15 | $form->default_values( 16 | { foo => 'x', 17 | bar => 'y', 18 | } ); 19 | 20 | $form->process; 21 | 22 | like( $form->get_field('foo'), qr/value="x"/ ); 23 | 24 | like( $form->get_field('bar'), qr/value="y"/ ); 25 | like( $form->get_field('bar'), qr/checked="checked"/ ); 26 | -------------------------------------------------------------------------------- /t/form/end.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | my $end_form = qq{}; 12 | 13 | is( $form->end, $end_form ); 14 | -------------------------------------------------------------------------------- /t/form/force_error_message.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | $form->form_error_message('Forced Error Message')->force_error_message(1); 12 | 13 | my $field = $form->element('Text')->name('foo'); 14 | 15 | $field->constraint('Number'); 16 | 17 | $form->process( { foo => '1', } ); 18 | 19 | ok( !$form->has_errors ); 20 | 21 | my $xhtml = < 23 |
Forced Error Message
24 |
25 | 26 |
27 | 28 | EOF 29 | 30 | is( "$form", $xhtml ); 31 | -------------------------------------------------------------------------------- /t/form/form_error_message_class.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | $form->form_error_message('Errors!'); 12 | $form->form_error_message_class('x-class'); 13 | 14 | my $field = $form->element('Text')->name('foo'); 15 | 16 | $field->constraint('Number'); 17 | 18 | $form->process( { foo => 'a', } ); 19 | 20 | like( "$form", qr{\Q
Errors!
} ); 21 | -------------------------------------------------------------------------------- /t/form/get_parent.yml: -------------------------------------------------------------------------------- 1 | --- 2 | auto_fieldset: 1 3 | 4 | elements: 5 | - type: Block 6 | name: 'block_1' 7 | elements: 8 | - type: Block 9 | name: 'block_1_1' 10 | tag: span 11 | elements: 12 | - type: Text 13 | name: 'text_1_1_1' 14 | - type: Repeatable 15 | name: 'repeatable_1_2' 16 | elements: 17 | - type: Text 18 | name: 'rep_text' 19 | - type: Submit 20 | name: 'submit_2' 21 | -------------------------------------------------------------------------------- /t/form/has_errors.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 6; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->element('Text')->name('foo'); 11 | $form->element('Text')->name('bar'); 12 | $form->element('Text')->name('string'); 13 | 14 | $form->constraint( 'Number', 'foo', 'bar', 'string' ); 15 | 16 | $form->process( 17 | { foo => 1, 18 | bar => [ 2, 3 ], 19 | string => 'yada', 20 | } ); 21 | 22 | ok( !grep { $_ eq 'foo' } $form->has_errors ); 23 | ok( !grep { $_ eq 'bar' } $form->has_errors ); 24 | ok( grep { $_ eq 'string' } $form->has_errors ); 25 | 26 | ok( !$form->has_errors('foo') ); 27 | ok( !$form->has_errors('bar') ); 28 | 29 | ok( $form->has_errors('string') ); 30 | 31 | -------------------------------------------------------------------------------- /t/form/hidden_fields.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | $form->element('Hidden')->name('foo'); 12 | $form->element('Hidden')->name('bar'); 13 | 14 | my $xhtml 15 | = qq{}; 16 | 17 | is( $form->hidden_fields, $xhtml ); 18 | -------------------------------------------------------------------------------- /t/form/init_arg.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 3; 5 | use Test::Exception; 6 | 7 | use HTML::FormFu; 8 | 9 | { 10 | 11 | package MyApp::FormFu; 12 | use Moose; 13 | extends 'HTML::FormFu'; 14 | 15 | has 'my_attr' => ( is => 'ro', init_arg => 'mine' ); 16 | } 17 | 18 | my $form; 19 | lives_ok( sub { $form = MyApp::FormFu->new( mine => 'ok' ); }, 20 | "form construction doesn't die" ); 21 | ok( $form, 'form constructed ok' ); 22 | is( $form->my_attr, 'ok', 'attribute set' ); 23 | -------------------------------------------------------------------------------- /t/form/javascript.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | $form->auto_fieldset(1); 12 | $form->javascript('foo();'); 13 | 14 | # xhtml output 15 | 16 | my $xhtml = < 18 | 21 |
22 |
23 | 24 | EOF 25 | 26 | is( "$form", $xhtml ); 27 | -------------------------------------------------------------------------------- /t/form/languages.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use utf8; 4 | 5 | use Test::More tests => 2; 6 | 7 | use lib 't/lib'; 8 | use HTML::FormFu; 9 | 10 | my $form = HTML::FormFu->new( 11 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 12 | 13 | $form->load_config_file('t/form/languages.yml'); 14 | 15 | # Invalid 16 | { 17 | $form->process( { bar => 'foo', } ); 18 | 19 | ok( !$form->submitted_and_valid ); 20 | 21 | like( $form, qr/\QFeld muss ausgefüllt sein/ ); 22 | } 23 | 24 | -------------------------------------------------------------------------------- /t/form/languages.yml: -------------------------------------------------------------------------------- 1 | languages: 2 | - de 3 | 4 | elements: 5 | - name: foo 6 | - name: bar 7 | 8 | constraints: 9 | - Required 10 | 11 | -------------------------------------------------------------------------------- /t/form/model.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 3; 5 | 6 | use lib 't/lib'; 7 | use HTML::FormFu; 8 | 9 | my $form = HTML::FormFu->new; 10 | 11 | $form->default_model('+HTMLFormFu::MyModel'); 12 | 13 | my $model = $form->model; 14 | 15 | ok( $model == $form->model('HTMLFormFu::MyModel') ); 16 | 17 | isa_ok( $model, 'HTMLFormFu::MyModel' ); 18 | isa_ok( $model, 'HTML::FormFu::Model' ); 19 | -------------------------------------------------------------------------------- /t/form/multiple_same_named_fields.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | my $foo1 = $form->element('Text')->name('foo'); 11 | my $foo2 = $form->element('Text')->name('foo'); 12 | 13 | $form->process( { foo => [qw/ a b /], } ); 14 | 15 | is( $foo1->render_data->{value}, 'a' ); 16 | is( $foo2->render_data->{value}, 'b' ); 17 | -------------------------------------------------------------------------------- /t/form/object/form: -------------------------------------------------------------------------------- 1 | [% FOREACH field = self.object.get_fields %][% field.name %] 2 | [% END %] -------------------------------------------------------------------------------- /t/form/param_array.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 3; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->element('Text')->name('foo'); 11 | $form->element('Text')->name('bar'); 12 | $form->element('Text')->name('baz'); 13 | 14 | $form->process( 15 | { foo => 'a', 16 | bar => [ 'b', 'c' ], 17 | } ); 18 | 19 | is_deeply( $form->param_array('foo'), ['a'] ); 20 | 21 | is_deeply( $form->param_array('bar'), [ 'b', 'c' ] ); 22 | 23 | is_deeply( $form->param_array('baz'), [] ); 24 | -------------------------------------------------------------------------------- /t/form/param_list.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 3; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->element('Text')->name('foo'); 11 | $form->element('Text')->name('bar'); 12 | $form->element('Text')->name('baz'); 13 | 14 | $form->process( 15 | { foo => 'a', 16 | bar => [ 'b', 'c' ], 17 | } ); 18 | 19 | is_deeply( [ $form->param_list('foo') ], ['a'] ); 20 | 21 | is_deeply( [ $form->param_list('bar') ], [ 'b', 'c' ] ); 22 | 23 | is_deeply( [ $form->param_list('baz') ], [] ); 24 | -------------------------------------------------------------------------------- /t/form/param_value.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 4; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->element('Text')->name('foo'); 11 | $form->element('Text')->name('bar'); 12 | $form->element('Text')->name('baz'); 13 | 14 | $form->process( 15 | { foo => 'a', 16 | bar => [ 'b', 'c' ], 17 | } ); 18 | 19 | is( $form->param_value('foo'), 'a' ); 20 | 21 | is( $form->param_value('bar'), 'b' ); 22 | 23 | my @baz = $form->param_value('baz'); 24 | 25 | # we got 1 value 26 | 27 | ok( @baz == 1 ); 28 | 29 | # it was undef 30 | 31 | is( $baz[0], undef ); 32 | -------------------------------------------------------------------------------- /t/form/params_ignore_underscore.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 3; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->params_ignore_underscore(1); 11 | 12 | $form->element('Text')->name('foo'); 13 | $form->element('Text')->name('bar'); 14 | $form->element('Text')->name('_baz'); 15 | 16 | $form->process( 17 | { foo => 'a', 18 | bar => 'b', 19 | _baz => 'c', 20 | } ); 21 | 22 | is_deeply( 23 | $form->params, 24 | { foo => 'a', 25 | bar => 'b', 26 | } ); 27 | 28 | ok( !grep { $_ eq '_baz' } $form->valid ); 29 | 30 | is( $form->param('_baz'), undef ); 31 | -------------------------------------------------------------------------------- /t/form/render_processed_value.yml: -------------------------------------------------------------------------------- 1 | --- 2 | render_processed_value: 1 3 | 4 | elements: 5 | - name: foo 6 | deflator: 7 | - type: Strftime 8 | strftime: '%d/%m/%Y' 9 | 10 | filter: 11 | - type: Regex 12 | match: 2007 13 | replace: 2006 14 | 15 | inflator: 16 | - type: DateTime 17 | parser: 18 | strptime: '%d/%m/%Y' 19 | 20 | - name: bar 21 | filter: 22 | - UpperCase 23 | 24 | -------------------------------------------------------------------------------- /t/form/start.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | my $start_form = qq{
}; 12 | 13 | is( $form->start, $start_form ); 14 | -------------------------------------------------------------------------------- /t/form/stash.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->stash->{foo} = 'bar'; 11 | 12 | $form->element('Text')->name('foo')->stash->{baz} = 'daz'; 13 | 14 | is( $form->render_data->{stash}{foo}, 'bar' ); 15 | 16 | is( $form->get_field('foo')->render_data->{stash}{baz}, 'daz' ); 17 | -------------------------------------------------------------------------------- /t/form/submitted_and_valid.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 3; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->element('Text')->name('foo')->constraint('Number'); 11 | 12 | ok( !$form->submitted_and_valid ); 13 | 14 | $form->process( { foo => 'a' } ); 15 | 16 | ok( !$form->submitted_and_valid ); 17 | 18 | $form->process( { foo => 1 } ); 19 | 20 | ok( $form->submitted_and_valid ); 21 | -------------------------------------------------------------------------------- /t/form/title_xml.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | $form->title_xml('My & Form'); 12 | 13 | my $form_xhtml = < 15 | 16 | EOF 17 | 18 | is( "$form", $form_xhtml ); 19 | 20 | -------------------------------------------------------------------------------- /t/i18n/add_localize_object_from_class.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use Test::More tests => 2; 4 | use HTML::FormFu; 5 | 6 | use lib 't/lib'; 7 | use HTMLFormFu::RegressLocalization; 8 | 9 | my $form = HTML::FormFu->new( 10 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 11 | 12 | $form->load_config_file('t/i18n/add_localize_object_from_class.yml'); 13 | 14 | like( "$form", qr/\bThis field is required\b/, "properly localized" ); 15 | 16 | like( 17 | "$form", 18 | qr/\bFoo blah Baz\b/, 19 | "properly localized (added object took effect)" 20 | ); 21 | -------------------------------------------------------------------------------- /t/i18n/add_localize_object_from_class.yml: -------------------------------------------------------------------------------- 1 | --- 2 | add_localize_object_from_class: 'HTMLFormFu::RegressLocalization' 3 | 4 | elements: 5 | - name: foo 6 | label_loc: form_constraint_required 7 | 8 | - name: bar 9 | label_loc: foobar 10 | -------------------------------------------------------------------------------- /t/inflators/array.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 8; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | my $field = $form->element('Text')->name('foo'); 11 | 12 | $field->inflator('DateTime')->parser( { strptime => '%d/%m/%Y' } ); 13 | 14 | $form->process( { foo => [ '31/12/2006', '01/01/2007' ], } ); 15 | 16 | my $value = $form->param_array('foo'); 17 | 18 | isa_ok( $value->[0], 'DateTime' ); 19 | 20 | is( $value->[0]->day, 31 ); 21 | is( $value->[0]->month, 12 ); 22 | is( $value->[0]->year, 2006 ); 23 | 24 | isa_ok( $value->[1], 'DateTime' ); 25 | 26 | is( $value->[1]->day, 1 ); 27 | is( $value->[1]->month, 1 ); 28 | is( $value->[1]->year, 2007 ); 29 | -------------------------------------------------------------------------------- /t/inflators/compounddatetime.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 7; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->load_config_file('t/inflators/compounddatetime.yml'); 11 | 12 | $form->process( 13 | { 'dob.day' => '31', 14 | 'dob.month' => '12', 15 | 'dob.year' => '1999', 16 | } ); 17 | 18 | ok( $form->submitted_and_valid ); 19 | 20 | isa_ok( $form->param_value('dob'), 'DateTime' ); 21 | 22 | my $dob = $form->params->{dob}; 23 | 24 | isa_ok( $dob, 'DateTime' ); 25 | 26 | is( $dob->day, '31' ); 27 | is( $dob->month, '12' ); 28 | is( $dob->year, '1999' ); 29 | 30 | # check strptime 31 | 32 | is( "$dob", "31-12-1999" ); 33 | -------------------------------------------------------------------------------- /t/inflators/compounddatetime.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | elements: 4 | - type: Multi 5 | name: dob 6 | 7 | elements: 8 | - name: day 9 | - name: month 10 | - name: year 11 | 12 | inflators: 13 | type: CompoundDateTime 14 | strptime: '%d-%m-%Y' 15 | -------------------------------------------------------------------------------- /t/inflators/compounddatetime_field_order.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 7; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->load_config_file('t/inflators/compounddatetime_field_order.yml'); 11 | 12 | $form->process( 13 | { 'dob.d' => '31', 14 | 'dob.m' => '12', 15 | 'dob.y' => '1999', 16 | } ); 17 | 18 | ok( $form->submitted_and_valid ); 19 | 20 | isa_ok( $form->param_value('dob'), 'DateTime' ); 21 | 22 | my $dob = $form->params->{dob}; 23 | 24 | isa_ok( $dob, 'DateTime' ); 25 | 26 | is( $dob->day, '31' ); 27 | is( $dob->month, '12' ); 28 | is( $dob->year, '1999' ); 29 | 30 | # check strptime 31 | 32 | is( "$dob", "12-31-1999" ); 33 | -------------------------------------------------------------------------------- /t/inflators/compounddatetime_field_order.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | elements: 4 | - type: Multi 5 | name: dob 6 | 7 | elements: 8 | - name: m 9 | - name: d 10 | - name: y 11 | 12 | inflators: 13 | type: CompoundDateTime 14 | strptime: '%m-%d-%Y' 15 | field_order: ['month', 'day', 'year'] 16 | -------------------------------------------------------------------------------- /t/inflators/datetime_optional.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->element('Text')->name('foo')->inflator('DateTime') 11 | ->parser( { strptime => '%d/%m/%Y' } ); 12 | 13 | $form->process( { foo => "" } ); 14 | 15 | ok( $form->submitted_and_valid ); 16 | 17 | -------------------------------------------------------------------------------- /t/inflators/datetime_parser.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 5; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->element('Text')->name('foo')->inflator('DateTime') 11 | ->parser( { strptime => '%d/%m/%Y' } ); 12 | 13 | $form->process( { foo => '31/12/2006' } ); 14 | 15 | ok( $form->submitted_and_valid ); 16 | 17 | my $value = $form->params->{foo}; 18 | 19 | isa_ok( $value, 'DateTime' ); 20 | 21 | is( $value->day, 31 ); 22 | is( $value->month, 12 ); 23 | is( $value->year, 2006 ); 24 | -------------------------------------------------------------------------------- /t/inflators/datetime_regex.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 4; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->element('Text')->name('foo'); 11 | 12 | $form->inflator('DateTime')->parser( 13 | { regex => qr/^ (\d{2}) \/ (\d{2}) \/ (\d{4}) $/x, 14 | params => [qw/ month day year /], 15 | } ); 16 | 17 | $form->process( { foo => '12/31/2006' } ); 18 | 19 | ok( !$form->has_errors ); 20 | 21 | my $value = $form->params->{foo}; 22 | 23 | is( $value->day, 31 ); 24 | is( $value->month, 12 ); 25 | is( $value->year, 2006 ); 26 | -------------------------------------------------------------------------------- /t/inflators/datetime_regex_string.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 4; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->element('Text')->name('foo'); 11 | 12 | $form->inflator('DateTime')->parser( 13 | { regex => '^(\d{2})\/(\d{2})\/(\d{4})$', 14 | params => [qw/ month day year /], 15 | } ); 16 | 17 | $form->process( { foo => '12/31/2006' } ); 18 | 19 | ok( !$form->has_errors ); 20 | 21 | my $value = $form->params->{foo}; 22 | 23 | is( $value->day, 31 ); 24 | is( $value->month, 12 ); 25 | is( $value->year, 2006 ); 26 | -------------------------------------------------------------------------------- /t/inflators/datetime_strptime.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->element('Text')->name('foo')->inflator('DateTime') 11 | ->parser( { strptime => '%d/%m/%Y' } )->strptime('%d/%m/%Y'); 12 | 13 | $form->element('Text')->name('bar')->inflator('DateTime') 14 | ->parser( { strptime => '%d/%m/%Y' } ) 15 | ->strptime( { pattern => '%m-%d-%Y' } ); 16 | 17 | $form->process( 18 | { foo => '31/12/2006', 19 | bar => '1/07/2007', 20 | } ); 21 | 22 | is( $form->params->{foo}, "31/12/2006" ); 23 | is( $form->params->{bar}, "07-01-2007" ); 24 | -------------------------------------------------------------------------------- /t/inflators/datetime_timezone.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->element('Text')->name('foo')->inflator('DateTime') 11 | ->parser( { strptime => '%Y-%m-%d %H:%M' } ) 12 | ->strptime('%H:%M [%Y-%m-%d] %z')->time_zone('Europe/Rome'); 13 | 14 | $form->process( { foo => '2008-07-23 08:52', } ); 15 | 16 | is( ref $form->params->{foo}->time_zone, 'DateTime::TimeZone::Europe::Rome' ); 17 | is( $form->params->{foo}, '08:52 [2008-07-23] +0200' ); 18 | -------------------------------------------------------------------------------- /t/inflators/datetime_with_constraint.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 5; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | # yaml config uses references to share the same parser spec between 11 | # the constraint and inflator 12 | 13 | $form->load_config_file('t/inflators/datetime_with_constraint.yml'); 14 | 15 | $form->process( { foo => '31-12-2006' } ); 16 | 17 | ok( $form->submitted_and_valid ); 18 | 19 | my $value = $form->params->{foo}; 20 | 21 | isa_ok( $value, 'DateTime' ); 22 | 23 | is( $value->day, 31 ); 24 | is( $value->month, 12 ); 25 | is( $value->year, 2006 ); 26 | -------------------------------------------------------------------------------- /t/inflators/datetime_with_constraint.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - name: foo 4 | 5 | constraints: 6 | - type: DateTime 7 | parser: &PARSER 8 | strptime: '%d-%m-%Y' 9 | 10 | inflators: 11 | - type: DateTime 12 | parser: *PARSER 13 | -------------------------------------------------------------------------------- /t/internals/default_args-types.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->load_config_file('t/internals/default_args-types.yml'); 11 | 12 | # default_args->{constraints} ISA ARRAY 13 | # elements->[0]->{constraints} ISA HASH 14 | 15 | my $field = $form->get_field('foo'); 16 | 17 | ok( $field->get_constraint( { type => 'Required' } ) ); 18 | 19 | ok( $field->get_constraint( { type => 'DateTime' } ) ); 20 | -------------------------------------------------------------------------------- /t/internals/default_args-types.yml: -------------------------------------------------------------------------------- 1 | --- 2 | auto_fieldset: 1 3 | 4 | default_args: 5 | elements: 6 | DateTime: 7 | constraints: 8 | - type: DateTime 9 | parser: 10 | strptime: '%Y-%m-%d %H:%M:00' 11 | 12 | elements: 13 | - type: DateTime 14 | name: foo 15 | constraints: 16 | type: Required 17 | -------------------------------------------------------------------------------- /t/lib/HTMLFormFu/DBICUniqueFake.pm: -------------------------------------------------------------------------------- 1 | package HTMLFormFu::DBICUniqueFake; 2 | 3 | use Moose; 4 | 5 | extends 'HTML::FormFu::Constraint'; 6 | 7 | has id_field => ( is => 'rw', traits => ['Chained'] ); 8 | 9 | sub constrain_value { 10 | my ( $self, $value ) = @_; 11 | 12 | return 1 if !defined $value || $value eq ''; 13 | 14 | return 1; 15 | } 16 | 17 | 1; 18 | 19 | -------------------------------------------------------------------------------- /t/lib/HTMLFormFu/ElementSetup.pm: -------------------------------------------------------------------------------- 1 | package HTMLFormFu::ElementSetup; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use base 'HTML::FormFu::Element::Text'; 7 | 8 | sub setup { 9 | my ($self) = @_; 10 | 11 | $::name = $self->name; 12 | } 13 | 14 | 1; 15 | -------------------------------------------------------------------------------- /t/lib/HTMLFormFu/I18N.pm: -------------------------------------------------------------------------------- 1 | package HTMLFormFu::I18N; 2 | use strict; 3 | use warnings; 4 | 5 | use base 'Locale::Maketext'; 6 | 7 | *loc = \&localize; 8 | 9 | sub localize { 10 | my $self = shift; 11 | 12 | return $self->maketext(@_); 13 | } 14 | 15 | 1; 16 | -------------------------------------------------------------------------------- /t/lib/HTMLFormFu/I18N/en.pm: -------------------------------------------------------------------------------- 1 | package HTMLFormFu::I18N::en; 2 | use strict; 3 | use warnings; 4 | 5 | use base qw( HTMLFormFu::I18N ); 6 | 7 | our %Lexicon = ( 8 | test_label => 'My Label', 9 | test_comment => 'My Comment', 10 | test_default_value => 'My Default', 11 | test_two_args => 'My [_1] [_2] args', 12 | label_foo => 'Foo label', 13 | label_form_bar => 'Bar label', 14 | form_validator_htmlformfu_myvalidator => 'myvalidator error!', 15 | bar_title => 'The Bar Title', 16 | ); 17 | 18 | 1; 19 | -------------------------------------------------------------------------------- /t/lib/HTMLFormFu/MyDeflator.pm: -------------------------------------------------------------------------------- 1 | package HTMLFormFu::MyDeflator; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use base 'HTML::FormFu::Deflator'; 7 | 8 | sub deflator { 9 | my ( $self, $value ) = @_; 10 | 11 | return if !defined $value; 12 | 13 | return $value->{value}; 14 | } 15 | 16 | 1; 17 | -------------------------------------------------------------------------------- /t/lib/HTMLFormFu/MyFormRole.pm: -------------------------------------------------------------------------------- 1 | package HTMLFormFu::MyFormRole; 2 | use Moose::Role; 3 | 4 | sub custom_role_method { 5 | my ($self) = @_; 6 | 7 | return sprintf "form ID: %s", $self->id; 8 | } 9 | 10 | 1; 11 | -------------------------------------------------------------------------------- /t/lib/HTMLFormFu/MyModel.pm: -------------------------------------------------------------------------------- 1 | package HTMLFormFu::MyModel; 2 | 3 | use base 'HTML::FormFu::Model'; 4 | 5 | 1; 6 | -------------------------------------------------------------------------------- /t/lib/HTMLFormFu/MyObject.pm: -------------------------------------------------------------------------------- 1 | package HTMLFormFu::MyObject; 2 | 3 | use strict; 4 | use warnings; 5 | use Carp qw( confess ); 6 | 7 | #use overload 8 | # '""' => sub { confess "overload called on object" }, 9 | # bool => sub { 1 }, 10 | # fallback => 1; 11 | 12 | sub new { 13 | my ( $class, $value ) = @_; 14 | 15 | return bless { value => $value }, $class; 16 | } 17 | 18 | 1; 19 | -------------------------------------------------------------------------------- /t/lib/HTMLFormFu/MyValidator.pm: -------------------------------------------------------------------------------- 1 | package HTMLFormFu::MyValidator; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use base 'HTML::FormFu::Validator'; 7 | 8 | sub validate_value { 9 | my ( $self, $value, $params ) = @_; 10 | 11 | die HTML::FormFu::Exception::Validator->new 12 | if $value eq 'foo'; 13 | 14 | return 1; 15 | } 16 | 17 | 1; 18 | -------------------------------------------------------------------------------- /t/lib/HTMLFormFu/RegressLocalization.pm: -------------------------------------------------------------------------------- 1 | package HTMLFormFu::RegressLocalization; 2 | use base qw(Locale::Maketext); 3 | 4 | sub localize { 5 | shift->maketext(@_); 6 | } 7 | 8 | 1; 9 | -------------------------------------------------------------------------------- /t/lib/HTMLFormFu/RegressLocalization/en.pm: -------------------------------------------------------------------------------- 1 | package HTMLFormFu::RegressLocalization::en; 2 | use base qw( HTMLFormFu::RegressLocalization ); 3 | 4 | our %Lexicon = ( foobar => "Foo blah Baz", ); 5 | 6 | 1; 7 | -------------------------------------------------------------------------------- /t/lib/MyApp/Schema.pm: -------------------------------------------------------------------------------- 1 | package MyApp::Schema; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use base 'DBIx::Class::Schema'; 7 | 8 | __PACKAGE__->load_classes; 9 | 10 | 1; 11 | 12 | -------------------------------------------------------------------------------- /t/lib/MyApp/Schema/Dongle.pm: -------------------------------------------------------------------------------- 1 | package MyApp::Schema::Dongle; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use base 'DBIx::Class'; 7 | 8 | __PACKAGE__->load_components(qw/ PK::Auto Core /); 9 | 10 | __PACKAGE__->table("dongle"); 11 | 12 | __PACKAGE__->add_columns( 13 | "person_id", 14 | { data_type => "INT", 15 | is_nullable => 0, 16 | size => 10, 17 | extra => { unsigned => 1, }, 18 | }, 19 | "dongle", 20 | { data_type => "VARCHAR", 21 | is_nullable => 0, 22 | size => 10, 23 | }, 24 | ); 25 | 26 | __PACKAGE__->set_primary_key("person_id"); 27 | 28 | __PACKAGE__->belongs_to( 29 | person => 'Person', 30 | { 'foreign.person_id' => 'self.person_id' } ); 31 | 32 | 1; 33 | 34 | -------------------------------------------------------------------------------- /t/load_config/config_file_path/form.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - name: found-me 4 | -------------------------------------------------------------------------------- /t/load_config/config_file_path2/form.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - name: new-found-me 4 | -------------------------------------------------------------------------------- /t/load_config/load_config_file_constraint_regex.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new->load_config_file( 9 | 't/load_config/load_config_file_constraint_regex.yml'); 10 | 11 | { 12 | $form->process( { foo => "foo bar" } ); 13 | 14 | ok( $form->valid('foo') ); 15 | } 16 | 17 | { 18 | $form->process( { foo => "\n" } ); 19 | 20 | ok( $form->has_errors('foo') ); 21 | } 22 | -------------------------------------------------------------------------------- /t/load_config/load_config_file_constraint_regex.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - type: Text 4 | name: foo 5 | constraints: 6 | - type: Not_Regex 7 | regex: '^\n*$' 8 | -------------------------------------------------------------------------------- /t/load_config/load_config_file_fieldset.yml: -------------------------------------------------------------------------------- 1 | --- 2 | legend: Jimi 3 | elements: 4 | - type: Text 5 | name: age 6 | comment: x 7 | label: Age 8 | constraints: 9 | - type: Integer 10 | message: No integer. 11 | - type: Integer 12 | message: This too! 13 | - type: Text 14 | name: name 15 | label: Name 16 | - type: Hidden 17 | name: ok 18 | value: OK 19 | -------------------------------------------------------------------------------- /t/load_config/load_config_file_form.yml: -------------------------------------------------------------------------------- 1 | --- 2 | action: /foo/bar 3 | id: form 4 | elements: 5 | - type: Fieldset 6 | load_config_file: t/load_config/load_config_file_fieldset.yml 7 | constraints: 8 | - type: Required 9 | names: [age, name] 10 | message: Missing value. 11 | filters: HTMLEscape 12 | -------------------------------------------------------------------------------- /t/load_config/load_config_file_multi_stream.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 3; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new->load_config_file( 9 | 't/load_config/load_config_file_multi_stream.yml'); 10 | 11 | my ( $foo, $bar, $baz ) = @{ $form->get_fields }; 12 | 13 | ok( $foo->get_constraint ); 14 | ok( $bar->get_constraint ); 15 | 16 | # no constraint 17 | ok( !$baz->get_constraint ); 18 | 19 | -------------------------------------------------------------------------------- /t/load_config/load_config_file_multi_stream.yml: -------------------------------------------------------------------------------- 1 | --- 2 | auto_fieldset: 1 3 | 4 | elements: 5 | - name: foo 6 | - name: bar 7 | 8 | constraints: 9 | - type: Required 10 | 11 | # baz below won't have a constraint, because it's loaded after the above 12 | # call to constraints() 13 | 14 | --- 15 | elements: 16 | - name: baz 17 | -------------------------------------------------------------------------------- /t/load_config/load_config_file_multiple.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 7; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new->load_config_file( 9 | 't/load_config/load_config_file_multiple.yml'); 10 | 11 | is( $form->action, '/foo' ); 12 | 13 | my $elems = $form->get_all_elements; 14 | 15 | is( scalar @$elems, 3 ); 16 | 17 | is( $elems->[0]->type, 'Fieldset' ); 18 | is( $elems->[1]->type, 'Text' ); 19 | is( $elems->[2]->type, 'Text' ); 20 | 21 | is( $elems->[1]->name, 'foo' ); 22 | is( $elems->[2]->name, 'bar' ); 23 | 24 | -------------------------------------------------------------------------------- /t/load_config/load_config_file_multiple.yml: -------------------------------------------------------------------------------- 1 | --- 2 | auto_fieldset: 1 3 | load_config_file: 4 | - t/load_config/load_config_file_multiple1.yml 5 | - t/load_config/load_config_file_multiple2.yml 6 | -------------------------------------------------------------------------------- /t/load_config/load_config_file_multiple1.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - type: Text 4 | name: foo 5 | -------------------------------------------------------------------------------- /t/load_config/load_config_file_multiple2.yml: -------------------------------------------------------------------------------- 1 | --- 2 | action: /foo 3 | elements: 4 | - type: Text 5 | name: bar 6 | -------------------------------------------------------------------------------- /t/model/hashref_create_repeatable_without_nn.yml: -------------------------------------------------------------------------------- 1 | --- 2 | auto_fieldset: 1 3 | 4 | elements: 5 | - type: Repeatable 6 | 7 | # it's now the default behaviour 8 | # increment_field_names: 1 9 | 10 | elements: 11 | - name: foo 12 | - name: bar 13 | - type: Submit 14 | name: submit 15 | -------------------------------------------------------------------------------- /t/multiple_text_fields.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | $form->element('Text')->name('foo'); 12 | $form->element('Text')->name('foo'); 13 | 14 | $form->process( { foo => [qw/ a b /], } ); 15 | 16 | my $xhtml = < 18 |
19 | 20 |
21 |
22 | 23 |
24 | 25 | EOF 26 | 27 | is( "$form", $xhtml ); 28 | -------------------------------------------------------------------------------- /t/nested/constraints/callbackonce.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 5; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->auto_fieldset( { nested_name => 'foo' } ); 11 | 12 | $form->element('Text')->name('bar')->constraint('CallbackOnce')->callback( 13 | sub { 14 | ok(1); 15 | return 1; 16 | } ); 17 | 18 | $form->element('Text')->name('baz')->constraint('CallbackOnce')->callback( 19 | sub { 20 | ok(1); 21 | return 1; 22 | } ); 23 | 24 | $form->process( 25 | { 'foo.bar' => 'x', 26 | 'foo.baz' => [ 1, 2 ], 27 | } ); 28 | 29 | ok( !$form->has_errors('foo.bar') ); 30 | ok( !$form->has_errors('foo.baz') ); 31 | 32 | ok( !$form->has_errors ); 33 | 34 | -------------------------------------------------------------------------------- /t/nested/constraints/equal.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 3; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->auto_fieldset( { nested_name => 'foo' } ); 11 | 12 | $form->element('Text')->name('bar')->constraint('Equal')->others('foo.baz'); 13 | 14 | $form->element('Text')->name('baz'); 15 | 16 | { 17 | $form->process( 18 | { 'foo.bar' => 'x', 19 | 'foo.baz' => 'x', 20 | } ); 21 | 22 | ok( !$form->has_errors('foo.bar') ); 23 | ok( !$form->has_errors ); 24 | } 25 | 26 | { 27 | $form->process( 28 | { 'foo.bar' => 'x', 29 | 'foo.baz' => 'y', 30 | } ); 31 | 32 | ok( !$form->has_errors('foo.bar') ); 33 | } 34 | -------------------------------------------------------------------------------- /t/nested/constraints/required.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->auto_fieldset( { nested_name => 'foo' } ); 11 | 12 | $form->element('Text')->name('bar')->constraint('Required'); 13 | $form->element('Text')->name('baz')->constraint('Required'); 14 | 15 | $form->process( { 'foo.bar' => 'x', } ); 16 | 17 | ok( !$form->has_errors('foo.bar') ); 18 | 19 | ok( $form->has_errors('foo.baz') ); 20 | -------------------------------------------------------------------------------- /t/nested/element_name.yml: -------------------------------------------------------------------------------- 1 | --- 2 | auto_id: '%n' 3 | auto_fieldset: 4 | nested_name: foo 5 | 6 | elements: 7 | - name: bar 8 | 9 | - type: Block 10 | nested_name: baz 11 | elements: 12 | - name: 0 13 | -------------------------------------------------------------------------------- /t/nested/elements/block_repeatable_multi_named.yml: -------------------------------------------------------------------------------- 1 | --- 2 | auto_fieldset: 1 3 | 4 | elements: 5 | - type: Repeatable 6 | nested_name: nested 7 | counter_name: counter 8 | 9 | elements: 10 | - name: foo 11 | 12 | - type: Multi 13 | name: multi 14 | elements: 15 | - name: bar 16 | - name: baz 17 | -------------------------------------------------------------------------------- /t/nested/elements/block_repeatable_multi_named_filter.yml: -------------------------------------------------------------------------------- 1 | --- 2 | auto_fieldset: 1 3 | 4 | elements: 5 | - type: Hidden 6 | name: count 7 | 8 | - type: Repeatable 9 | nested_name: nested 10 | counter_name: counter 11 | 12 | elements: 13 | - name: foo 14 | 15 | - type: Multi 16 | name: multi 17 | elements: 18 | - name: bar 19 | - name: baz 20 | filter: 21 | - CompoundJoin 22 | -------------------------------------------------------------------------------- /t/nested/elements/block_without_name.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->load_config_file('t/nested/elements/block_without_name.yml'); 11 | 12 | is( $form->get_field('bar')->nested_name, 'foo.bar' ); 13 | 14 | -------------------------------------------------------------------------------- /t/nested/elements/block_without_name.yml: -------------------------------------------------------------------------------- 1 | --- 2 | auto_fieldset: 3 | nested_name: foo 4 | 5 | elements: 6 | - type: Block 7 | elements: 8 | - name: bar 9 | -------------------------------------------------------------------------------- /t/nested/elements/multi.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | $form->auto_fieldset( { nested_name => 'nested' } ); 12 | 13 | my $multi = $form->element('Multi'); 14 | 15 | $multi->element('Text')->name('foo'); 16 | 17 | my $form_xhtml = < 19 |
20 |
21 | 22 | 23 | 24 |
25 |
26 | 27 | EOF 28 | 29 | is( "$form", $form_xhtml, 'stringified form' ); 30 | 31 | -------------------------------------------------------------------------------- /t/nested/elements/radio.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 4; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | $form->auto_fieldset( { nested_name => 'radio' } ); 12 | 13 | $form->element('Radio')->name('foo')->value('foox'); 14 | 15 | is( "$form", < 17 |
18 |
19 | 20 |
21 |
22 | 23 | EOF 24 | 25 | { 26 | $form->process( { 'radio.foo' => 'foox', } ); 27 | 28 | ok( $form->valid('radio.foo') ); 29 | 30 | is( $form->param('radio.foo'), 'foox' ); 31 | 32 | like( $form->get_field('foo'), qr/checked/ ); 33 | } 34 | -------------------------------------------------------------------------------- /t/nested/elements/repeatable_repeatable.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - type: Hidden 4 | name: count 5 | 6 | - type: Repeatable 7 | nested_name: outer 8 | counter_name: count 9 | elements: 10 | - name: foo 11 | 12 | - type: Hidden 13 | name: count 14 | 15 | - type: Repeatable 16 | nested_name: inner 17 | counter_name: count 18 | 19 | elements: 20 | - name: bar 21 | -------------------------------------------------------------------------------- /t/nested/elements/select_same_name.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new( 9 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 10 | 11 | $form->load_config_file('t/nested/elements/select_same_name.yml'); 12 | 13 | $form->process( { 'x.foo' => [ 1, 2 ], } ); 14 | 15 | is( "$form", < 17 |
18 |
19 | 23 |
24 |
25 | 29 |
30 |
31 | 32 | EOF 33 | -------------------------------------------------------------------------------- /t/nested/elements/select_same_name.yml: -------------------------------------------------------------------------------- 1 | --- 2 | auto_fieldset: 3 | nested_name: x 4 | 5 | elements: 6 | - type: Select 7 | name: foo 8 | options: 9 | - [1, One] 10 | - [2, Two] 11 | 12 | - type: Select 13 | name: foo 14 | options: 15 | - [1, One] 16 | - [2, Two] 17 | -------------------------------------------------------------------------------- /t/nested/filters/regex.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->auto_fieldset( { nested_name => 'foo' } ); 11 | 12 | $form->element('Text')->name('bar'); 13 | $form->element('Text')->name('baz'); 14 | 15 | $form->filters( 16 | { type => 'Regex', 17 | names => [qw/ foo.bar foo.baz /], 18 | match => 'a', 19 | replace => 'A', 20 | } ); 21 | 22 | $form->process( 23 | { 'foo.bar' => 'abc', 24 | 'foo.baz' => 'def', 25 | } ); 26 | 27 | is( $form->param('foo.bar'), 'Abc' ); 28 | is( $form->param('foo.baz'), 'def' ); 29 | 30 | -------------------------------------------------------------------------------- /t/nested/form/render_processed_value.yml: -------------------------------------------------------------------------------- 1 | --- 2 | render_processed_value: 1 3 | auto_fieldset: 4 | nested_name: ack 5 | 6 | elements: 7 | - name: foo 8 | deflator: 9 | - type: Strftime 10 | strftime: '%d/%m/%Y' 11 | 12 | filter: 13 | - type: Regex 14 | match: 2007 15 | replace: 2006 16 | 17 | inflator: 18 | - type: DateTime 19 | parser: 20 | strptime: '%d/%m/%Y' 21 | 22 | - name: bar 23 | filter: 24 | - UpperCase 25 | 26 | -------------------------------------------------------------------------------- /t/nested/form_input.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->auto_fieldset( { nested_name => 'foo' } ); 11 | 12 | my $bar = $form->element('Text')->name('bar'); 13 | 14 | $form->process( 15 | { 'foo.bar' => 'x', 16 | foo => { bar => 'x', }, 17 | } ); 18 | 19 | is_deeply( $form->input, { foo => { bar => 'x', }, }, ); 20 | -------------------------------------------------------------------------------- /t/nested/illegal_name.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | eval { $form->element( { name => 'foo.bar' } ); }; 11 | 12 | # died 13 | 14 | ok($@); 15 | -------------------------------------------------------------------------------- /t/nested/internals/form_processed_params.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->auto_fieldset( { nested_name => 'foo' } ); 11 | 12 | my $bar = $form->element('Text')->name('bar'); 13 | 14 | $form->process( 15 | { 'foo.bar' => 'x', 16 | foo => { bar => 'x', }, 17 | } ); 18 | 19 | is_deeply( $form->_processed_params, { foo => { bar => 'x', }, }, ); 20 | -------------------------------------------------------------------------------- /t/nested/params.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->auto_fieldset( { nested_name => 'foo' } ); 11 | 12 | $form->element('Text')->name('bar')->constraint('Number'); 13 | $form->element('Text')->name('baz')->constraint('Number'); 14 | $form->element('Text')->name('bag')->constraint('Number'); 15 | 16 | $form->process( 17 | { 'foo.bar' => 1, 18 | 'foo.baz' => [ 2, 3 ], 19 | 'foo.bag' => 'yada', 20 | 'foo.unknown' => 4, 21 | } ); 22 | 23 | is_deeply( 24 | $form->params, 25 | { foo => { 26 | bar => 1, 27 | baz => [ 2, 3 ], 28 | }, 29 | } ); 30 | 31 | -------------------------------------------------------------------------------- /t/nested/pre_expanded.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->auto_fieldset( { nested_name => 'foo' } ); 11 | 12 | $form->element('Text')->name('bar')->constraint('Number'); 13 | $form->element('Text')->name('baz')->constraint('Number'); 14 | $form->element('Text')->name('bag')->constraint('Number'); 15 | 16 | $form->process( 17 | { foo => { 18 | bar => 1, 19 | baz => [ 2, 3 ], 20 | bag => 'yada', 21 | unknown => 4, 22 | }, 23 | } ); 24 | 25 | is_deeply( 26 | $form->params, 27 | { foo => { 28 | bar => 1, 29 | baz => [ 2, 3 ], 30 | }, 31 | } ); 32 | 33 | -------------------------------------------------------------------------------- /t/plugins/stashvalid.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->load_config_file('t/plugins/stashvalid.yml'); 11 | 12 | $form->process( 13 | { foo => 'a', 14 | bar => 'b', 15 | } ); 16 | 17 | is( $form->stash->{foo}, 'a' ); 18 | is( $form->stash->{bar}, undef ); 19 | -------------------------------------------------------------------------------- /t/plugins/stashvalid.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - name: foo 4 | 5 | - name: bar 6 | 7 | plugins: 8 | - type: StashValid 9 | name: foo 10 | -------------------------------------------------------------------------------- /t/plugins/stashvalid_on_field.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; 5 | 6 | use HTML::FormFu; 7 | 8 | my $form = HTML::FormFu->new; 9 | 10 | $form->load_config_file('t/plugins/stashvalid_on_field.yml'); 11 | 12 | $form->process( 13 | { foo => 'a', 14 | bar => 'b', 15 | } ); 16 | 17 | is( $form->stash->{foo}, 'a' ); 18 | is( $form->stash->{bar}, undef ); 19 | -------------------------------------------------------------------------------- /t/plugins/stashvalid_on_field.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - name: foo 4 | plugin: StashValid 5 | 6 | - name: bar 7 | -------------------------------------------------------------------------------- /t/repeatable/clone.yml: -------------------------------------------------------------------------------- 1 | --- 2 | auto_fieldset: 1 3 | 4 | elements: 5 | - type: Hidden 6 | name: count 7 | 8 | - type: Repeatable 9 | nested_name: rep 10 | increment_field_names: 1 11 | counter_name: count 12 | elements: 13 | - name: foo 14 | - name: bar 15 | constraints: 16 | - Required 17 | -------------------------------------------------------------------------------- /t/repeatable/constraints/attach_errors_to.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - type: Hidden 4 | name: count 5 | 6 | - type: Repeatable 7 | nested_name: rep 8 | counter_name: count 9 | elements: 10 | - name: foo 11 | constraints: 12 | - type: AllOrNone 13 | others: 14 | rep.bar 15 | attach_errors_to: 16 | - rep.foo 17 | - rep.bar 18 | - name: bar 19 | -------------------------------------------------------------------------------- /t/repeatable/constraints/equal.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - type: Hidden 4 | name: count 5 | 6 | - type: Repeatable 7 | nested_name: rep 8 | increment_field_names: 1 9 | counter_name: count 10 | elements: 11 | - name: foo 12 | constraints: 13 | - type: Equal 14 | others: 15 | - bar 16 | - 'rep.baz' 17 | 18 | - name: bar 19 | - name: baz 20 | -------------------------------------------------------------------------------- /t/repeatable/constraints/required.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - type: Hidden 4 | name: count 5 | 6 | - type: Repeatable 7 | nested_name: rep 8 | increment_field_names: 1 9 | counter_name: count 10 | elements: 11 | - name: foo 12 | - name: bar 13 | constraints: 14 | - Required 15 | -------------------------------------------------------------------------------- /t/repeatable/constraints/required_not_increment_field_names.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - type: Hidden 4 | name: count 5 | 6 | - type: Repeatable 7 | increment_field_names: 0 8 | counter_name: count 9 | elements: 10 | - name: foo 11 | - name: bar 12 | constraints: 13 | - Required 14 | -------------------------------------------------------------------------------- /t/repeatable/constraints/required_not_nested.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - type: Hidden 4 | name: count 5 | 6 | - type: Repeatable 7 | increment_field_names: 1 8 | counter_name: count 9 | elements: 10 | - name: foo 11 | - name: bar 12 | constraints: 13 | - Required 14 | -------------------------------------------------------------------------------- /t/repeatable/constraints/when.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - type: Hidden 4 | name: count 5 | 6 | - type: Repeatable 7 | nested_name: rep 8 | increment_field_names: 1 9 | counter_name: count 10 | 11 | elements: 12 | - name: foo 13 | 14 | - name: bar 15 | constraints: 16 | - type: Required 17 | when: 18 | field: 'rep.foo' 19 | -------------------------------------------------------------------------------- /t/repeatable/repeatable/constraints/repeatable_any.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - type: Hidden 4 | name: outer_count 5 | 6 | - type: Repeatable 7 | counter_name: outer_count 8 | elements: 9 | - name: foo 10 | constraints: 11 | - 'Repeatable::Any' 12 | 13 | - type: Hidden 14 | name: inner_count 15 | 16 | - type: Repeatable 17 | counter_name: inner_count 18 | elements: 19 | - name: foo 20 | constraints: 21 | - 'Repeatable::Any' 22 | -------------------------------------------------------------------------------- /t/roles/block.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | use lib 't/lib'; 8 | 9 | my $form = HTML::FormFu->new( 10 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 11 | 12 | $form->load_config_file('t/roles/block.yml'); 13 | 14 | my $expected_form_xhtml = < 16 |
17 |
18 | 19 |
20 |
21 | 22 | EOF 23 | 24 | is( "$form", $expected_form_xhtml ); 25 | -------------------------------------------------------------------------------- /t/roles/block.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elements: 3 | - type: Block 4 | roles: 5 | - '+HTMLFormFu::MyBlockRole' 6 | elements: 7 | - name: foo 8 | -------------------------------------------------------------------------------- /t/roles/field.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | use lib 't/lib'; 8 | 9 | my $form = HTML::FormFu->new( 10 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 11 | 12 | $form->load_config_file('t/roles/field.yml'); 13 | 14 | my $expected_form_xhtml = < 16 |
17 |
18 | 19 |
20 |
21 | 22 | EOF 23 | 24 | is( "$form", $expected_form_xhtml ); 25 | -------------------------------------------------------------------------------- /t/roles/field.yml: -------------------------------------------------------------------------------- 1 | --- 2 | auto_fieldset: 1 3 | 4 | elements: 5 | - name: foo 6 | roles: 7 | - '+HTMLFormFu::MyFieldRole' 8 | -------------------------------------------------------------------------------- /t/roles/form.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use HTML::FormFu; 7 | use lib 't/lib'; 8 | 9 | my $form = HTML::FormFu->new( 10 | { tt_args => { INCLUDE_PATH => 'share/templates/tt/xhtml' } } ); 11 | 12 | $form->load_config_file('t/roles/form.yml'); 13 | 14 | is( $form->custom_role_method, "form ID: xxx" ); 15 | -------------------------------------------------------------------------------- /t/roles/form.yml: -------------------------------------------------------------------------------- 1 | --- 2 | id: xxx 3 | roles: 4 | - '+HTMLFormFu::MyFormRole' 5 | -------------------------------------------------------------------------------- /t/templates/field_layout: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /xt/circular_reference.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; 5 | use Test::Memory::Cycle; 6 | 7 | use HTML::FormFu; 8 | 9 | my $form = HTML::FormFu->new; 10 | 11 | $form->load_config_file('xt/circular_reference.yml'); 12 | 13 | memory_cycle_ok($form); 14 | 15 | memory_cycle_ok( $form->render_data ); 16 | --------------------------------------------------------------------------------