diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index e8e4a7c1..24322b98 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -8,6 +8,7 @@ en: custom_title: "Wizard" field: too_short: "%{label} must be at least %{min} characters" + required: "%{label} is required." none: "We couldn't find a wizard at that address." no_skip: "Wizard can't be skipped" export: diff --git a/lib/custom_wizard/builder.rb b/lib/custom_wizard/builder.rb index a9157c2b..53cbe4d3 100644 --- a/lib/custom_wizard/builder.rb +++ b/lib/custom_wizard/builder.rb @@ -154,7 +154,7 @@ class CustomWizard::Builder next if updater.errors.any? - data = updater.fields.to_h + data = updater.fields ## if the wizard has data from the previous steps make that accessible to the actions. if @submissions && @submissions.last && !@submissions.last.key?("submitted_at") @@ -324,13 +324,17 @@ class CustomWizard::Builder def validate_field(field, updater, step_template) value = updater.fields[field['id']] min_length = false + label = field['label'] || I18n.t("#{field['key']}.label") + + if field['required'] && !value + updater.errors.add(field['id'].to_s, I18n.t('wizard.field.required', label: label)) + end if is_text_type(field) min_length = field['min_length'] end if min_length && value.is_a?(String) && value.strip.length < min_length.to_i - label = field['label'] || I18n.t("#{field['key']}.label") updater.errors.add(field['id'].to_s, I18n.t('wizard.field.too_short', label: label, min: min_length.to_i)) end diff --git a/lib/custom_wizard/step_updater.rb b/lib/custom_wizard/step_updater.rb index c521924c..80428202 100644 --- a/lib/custom_wizard/step_updater.rb +++ b/lib/custom_wizard/step_updater.rb @@ -8,7 +8,7 @@ class CustomWizard::StepUpdater @wizard = wizard @step = step @refresh_required = false - @fields = fields + @fields = fields.to_h.with_indifferent_access @result = {} end diff --git a/spec/components/custom_wizard/builder_spec.rb b/spec/components/custom_wizard/builder_spec.rb index b5be4ca4..22d3a708 100644 --- a/spec/components/custom_wizard/builder_spec.rb +++ b/spec/components/custom_wizard/builder_spec.rb @@ -12,16 +12,40 @@ describe CustomWizard::Builder do ).read) end + let(:permitted_params) {[{"key":"param_key","value":"submission_param_key"}]} + let(:required_data) {[{"key":"nickname","connector":"equals","value":"name"}]} + let(:required_data_message) {"Nickname is required to match your name"} + let(:checkbox_field) {{"id":"checkbox","type":"checkbox","label":"Checkbox"}} + let(:composer_field) {{"id": "composer","label":"Composer","type":"composer"}} + let(:dropdown_categories_field) {{"id": "dropdown_categories","type": "dropdown","label": "Dropdown Categories","choices_type": "preset","choices_preset": "categories"}} + let(:tag_field) {{"id": "tag","type": "tag","label": "Tag","limit": "2"}} + let(:category_field) {{"id": "category","type": "category","limit": "1","label": "Category"}} + let(:image_field) {{"id": "image","type": "image","label": "Image"}} + let(:text_field) {{"id": "text","type": "text","min_length": "12","label": "Text"}} + let(:textarea_field) {{"id": "textarea","type": "textarea","min_length": "40","label": "Textarea"}} + let(:text_only_field) {{"id": "text_only","type": "text-only","label": "Text only"}} + let(:upload_field) {{"id": "upload","type": "upload","file_types": ".jpg,.png,.pdf","label": "Upload"}} + let(:user_selector_field) {{"id": "user_selector","type": "user-selector","label": "User selector"}} + let(:dropdown_groups_field) {{"id": "dropdown_groups","type": "dropdown","choices_type": "preset","choices_preset": "groups","label": "Dropdown Groups"}} + let(:dropdown_tags_field) {{"id": "dropdown_tags","type": "dropdown","choices_type": "preset","choices_preset": "tags","label": "Dropdown Tags"}} + let(:dropdown_custom_field) {{"id": "dropdown_custom","type": "dropdown","choices_type": "custom","choices": [{"key": "option_1","value": "Option 1"},{"key": "option_2","value": "Option 2"}]}} + let(:dropdown_translation_field) {{"id": "dropdown_translation","type": "dropdown","choices_type": "translation","choices_key": "key1.key2"}} + let(:dropdown_categories_filtered_field) {{"id": "dropdown_categories_filtered_field","type": "dropdown","choices_type": "preset","choices_preset": "categories","choices_filters": [{"key": "slug","value": "staff"}]}} + def build_wizard(t = template, u = user, build_opts = {}, params = {}) CustomWizard::Wizard.add_wizard(t) CustomWizard::Builder.new(u, 'welcome').build(build_opts, params) end - def add_submission_data - PluginStore.set("welcome_submissions", user.id, + def add_submission_data(data = {}) + PluginStore.set("welcome_submissions", user.id, { name: 'Angus', website: 'https://thepavilion.io' - ) + }.merge(data)) + end + + def get_submission_data + PluginStore.get("welcome_submissions", user.id) end it "returns no steps when disabled" do @@ -84,76 +108,77 @@ describe CustomWizard::Builder do end it 'saves permitted params' do - template['steps'][0]['permitted_params'] = [ - { - "key": "param_key", - "value": "submission_param_key" - } - ] + template['steps'][0]['permitted_params'] = permitted_params wizard = build_wizard(template, user, {}, param_key: 'param_value') - submissions = PluginStore.get("welcome_submissions", user.id) + submissions = get_submission_data expect(submissions.first['submission_param_key']).to eq('param_value') end - it 'ensures required data is present' do - - end - end - - context 'building fields' do - it 'returns field data correctly' do - + it 'is not permitted if required data is not present' do + template['steps'][0]['required_data'] = required_data + expect(build_wizard(template, user).steps[0].permitted).to eq(false) end - it 'returns checkbox fields correctly' do - + it "is not permitted if required data is not present" do + template['steps'][0]['required_data'] = required_data + add_submission_data(nickname: "John") + expect(build_wizard(template, user).steps[0].permitted).to eq(false) end - it 'returns upload fields correctly' do - + it 'it shows required data message if required data has message' do + template['steps'][0]['required_data'] = required_data + template['steps'][0]['required_data_message'] = required_data_message + add_submission_data(nickname: "John") + wizard = build_wizard(template, user) + expect(wizard.steps[0].permitted).to eq(false) + expect(wizard.steps[0].permitted_message).to eq(required_data_message) end - it 'returns category fields correctly' do - + it 'is permitted if required data is present' do + template['steps'][0]['required_data'] = required_data + PluginStore.set('welcome_submissions', user.id, nickname: "Angus", name: "Angus") + expect(build_wizard(template, user).steps[0].permitted).to eq(true) end - it 'returns tag fields correctly' do - + it 'returns field metadata' do + expect(build_wizard(template, user).steps[0].fields[0].label).to eq("

Name

") + expect(build_wizard(template, user).steps[0].fields[0].type).to eq("text") end - it 'returns custom dropdown fields correctly' do - - end - - it 'returns translated dropdown fields correctly' do - - end - - it 'returns preset dropdown fields correctly' do - - end - - it 'applies preset dropdown filters correctly' do - - end - - it 'prefils profile data correctly' do - + it 'returns fields' do + template['steps'][0]['fields'][1] = checkbox_field + expect(build_wizard(template, user).steps[0].fields.length).to eq(2) end end context 'on update' do context 'validation' do - it 'applies min length correctly' do - + it 'applies min length' do + template['steps'][0]['fields'][0]['min_length'] = 10 + wizard = build_wizard(template, user) + updater = wizard.create_updater(template['steps'][0]['id'], name: 'short') + updater.update + expect(updater.errors.messages[:name].first).to eq( + I18n.t('wizard.field.too_short', label: 'Name', min: 10) + ) end it 'standardises boolean entries' do - + template['steps'][0]['fields'][0] = checkbox_field + wizard = build_wizard(template, user) + updater = wizard.create_updater(template['steps'][0]['id'], checkbox: 'false') + updater.update + submissions = get_submission_data + expect(submissions.first['checkbox']).to eq(false) end it 'requires required fields' do - ## this may require additional work? + wizard = build_wizard + updater = wizard.create_updater(template['steps'][0]['id'], other_field: 'other') + updater.update + expect(updater.errors.messages[:name].first).to eq( + I18n.t('wizard.field.required', label: 'Name') + ) end context 'submisisons' do