diff --git a/app/forms/custom_fields/inputs/base/input.rb b/app/forms/custom_fields/inputs/base/input.rb index 2e160a5a6f5..6ea785e1e47 100644 --- a/app/forms/custom_fields/inputs/base/input.rb +++ b/app/forms/custom_fields/inputs/base/input.rb @@ -41,6 +41,10 @@ class CustomFields::Inputs::Base::Input < ApplicationForm @options = options end + def model + @object + end + def input_attributes base_input_attributes.merge( { diff --git a/app/forms/custom_fields/inputs/base/utils.rb b/app/forms/custom_fields/inputs/base/utils.rb index b6ee0ab0a2e..2eb232a39ee 100644 --- a/app/forms/custom_fields/inputs/base/utils.rb +++ b/app/forms/custom_fields/inputs/base/utils.rb @@ -27,6 +27,8 @@ #++ module CustomFields::Inputs::Base::Utils + delegate :attribute_name, to: :@custom_field + def base_input_attributes { name:, @@ -34,7 +36,8 @@ module CustomFields::Inputs::Base::Utils value:, required: required?, invalid: invalid?, - validation_message: + validation_message:, + help_text_options: { attribute_name: } } end @@ -55,7 +58,7 @@ module CustomFields::Inputs::Base::Utils end def qa_field_name - @custom_field.attribute_name(:kebab_case) + attribute_name(:kebab_case) end # used within autocompleter inputs diff --git a/lib/primer/open_project/forms/dsl/input_methods.rb b/lib/primer/open_project/forms/dsl/input_methods.rb index a2c94824e1a..5ff89481631 100644 --- a/lib/primer/open_project/forms/dsl/input_methods.rb +++ b/lib/primer/open_project/forms/dsl/input_methods.rb @@ -5,6 +5,22 @@ module Primer module Forms module Dsl module InputMethods + def multi(**, &) + super(**decorate_options(**), &) + end + + def check_box(**, &) + super(**decorate_options(**), &) + end + + def radio_button_group(**, &) + super(**decorate_options(**), &) + end + + def check_box_group(**, &) + super(**decorate_options(**), &) + end + def autocompleter(**, &) add_input AutocompleterInput.new(builder:, form:, **decorate_options(**), &) end @@ -45,9 +61,10 @@ module Primer add_input WorkPackageAutocompleterInput.new(builder:, form:, **decorate_options(**), &) end - def decorate_options(include_help_text: true, **options) - if include_help_text && supports_help_texts?(builder.object) - options[:label] = form.wrap_attribute_label_with_help_text(options[:label], options[:name]) + def decorate_options(include_help_text: true, help_text_options: {}, **options) + if include_help_text && supports_help_texts?(form.model) + attribute_name = help_text_options[:attribute_name] || options[:name] + options[:label] = form.wrap_attribute_label_with_help_text(options[:label], attribute_name) end options end diff --git a/spec/features/projects/project_custom_fields/overview_page/dialog/attribute_help_texts_spec.rb b/spec/features/projects/project_custom_fields/overview_page/dialog/attribute_help_texts_spec.rb new file mode 100644 index 00000000000..d5c4ec6060c --- /dev/null +++ b/spec/features/projects/project_custom_fields/overview_page/dialog/attribute_help_texts_spec.rb @@ -0,0 +1,247 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) the OpenProject GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See COPYRIGHT and LICENSE files for more details. +#++ + +require "spec_helper" +require_relative "../shared_context" + +RSpec.describe "Edit project custom fields on project overview page", "attribute help texts", :js, :selenium do + include_context "with seeded projects, members and project custom fields" + include API::V3::Utilities::PathHelper + + let(:overview_page) { Pages::Projects::Show.new(project) } + let(:edit_dialog) { Components::Projects::ProjectCustomFields::EditDialog.new(project, section) } + + before do + login_as member_with_project_attributes_edit_permissions + overview_page.visit_page + end + + context "for input fields section" do + let(:section) { section_for_input_fields } + + context "without attribute help texts defined" do + before do + overview_page.open_edit_dialog_for_section(section) + end + + it "shows field labels without help text link" do + edit_dialog.expect_title section.name + + edit_dialog.expect_field_label_without_help_text "Boolean field" + edit_dialog.expect_field_label_without_help_text "Date field" + edit_dialog.expect_field_label_without_help_text "Float field" + edit_dialog.expect_field_label_without_help_text "Integer field" + edit_dialog.expect_field_label_without_help_text "Link field" + edit_dialog.expect_field_label_without_help_text "String field" + edit_dialog.expect_field_label_without_help_text "Text field" + end + end + + context "with attribute help texts defined" do + let!(:boolean_help_text) { create(:project_help_text, attribute_name: boolean_project_custom_field.attribute_name) } + let!(:date_help_text) { create(:project_help_text, attribute_name: date_project_custom_field.attribute_name) } + let!(:float_help_text) { create(:project_help_text, attribute_name: float_project_custom_field.attribute_name) } + let!(:integer_help_text) { create(:project_help_text, attribute_name: integer_project_custom_field.attribute_name) } + let!(:link_help_text) { create(:project_help_text, attribute_name: link_project_custom_field.attribute_name) } + let!(:string_help_text) { create(:project_help_text, attribute_name: string_project_custom_field.attribute_name) } + let!(:text_help_text) { create(:project_help_text, attribute_name: text_project_custom_field.attribute_name) } + + before do + overview_page.open_edit_dialog_for_section(section) + end + + it "shows field labels with help text link" do + edit_dialog.expect_title section.name + + edit_dialog.expect_field_label_with_help_text "Boolean field" + edit_dialog.expect_field_label_with_help_text "Date field" + edit_dialog.expect_field_label_with_help_text "Float field" + edit_dialog.expect_field_label_with_help_text "Integer field" + edit_dialog.expect_field_label_with_help_text "Link field" + edit_dialog.expect_field_label_with_help_text "String field" + edit_dialog.expect_field_label_with_help_text "Text field" + end + + context "without attachments" do + it "shows help text modal on clicking help text link" do + edit_dialog.expect_title section.name + + edit_dialog.click_help_text_link_for_label "Date field" + + expect(page).to have_modal "Date field" + within_modal "Date field" do + expect(page).to have_text "Attribute help text" + expect(page).to have_no_heading "Attachments" + + click_on "Close" + end + expect(page).to have_no_modal "Date field" + end + end + + context "with attachments" do + let!(:attachments) { create_list(:attachment, 2, container: integer_help_text) } + + it "shows help text modal, including attachments, on clicking help text link" do + edit_dialog.expect_title section.name + + edit_dialog.click_help_text_link_for_label "Integer field" + expect(page).to have_modal "Integer field" + within_modal "Integer field" do + expect(page).to have_text "Attribute help text" + + expect(page).to have_heading "Attachments" + expect(page).to have_list_item count: 2 + expect(page).to have_list_item text: "file-1.test" + expect(page).to have_list_item text: "file-2.test" + + attachment_window = window_opened_by do + click_on "file-1.test" + end + within_window(attachment_window) do + expect(page).to have_current_path api_v3_paths.attachment_content(attachments.first.id) + expect(page).to have_text "test content" + end + attachment_window.close + + click_on "Close" + end + expect(page).to have_no_modal "Integer field" + end + end + end + end + + context "for select fields section" do + let(:section) { section_for_select_fields } + + context "without attribute help texts defined" do + before do + overview_page.open_edit_dialog_for_section(section) + end + + it "shows field labels without help text link" do + edit_dialog.expect_title section.name + + edit_dialog.expect_field_label_without_help_text "List field" + edit_dialog.expect_field_label_without_help_text "Version field" + edit_dialog.expect_field_label_without_help_text "User field" + end + end + + context "with attribute help texts defined" do + let!(:list_help_text) { create(:project_help_text, attribute_name: list_project_custom_field.attribute_name) } + let!(:version_help_text) { create(:project_help_text, attribute_name: version_project_custom_field.attribute_name) } + let!(:user_help_text) { create(:project_help_text, attribute_name: user_project_custom_field.attribute_name) } + + before do + overview_page.open_edit_dialog_for_section(section) + end + + it "shows field labels with help text link" do + edit_dialog.expect_title section.name + + edit_dialog.expect_field_label_with_help_text "List field" + edit_dialog.expect_field_label_with_help_text "Version field" + edit_dialog.expect_field_label_with_help_text "User field" + end + + it "shows help text modal on clicking help text link" do + edit_dialog.expect_title section.name + + edit_dialog.click_help_text_link_for_label "User field" + + expect(page).to have_modal "User field" + within_modal "User field" do + expect(page).to have_text "Attribute help text" + + click_on "Close" + end + expect(page).to have_no_modal "User field" + end + end + end + + context "for multi select fields section" do + let(:section) { section_for_multi_select_fields } + + context "without attribute help texts defined" do + before do + overview_page.open_edit_dialog_for_section(section) + end + + it "shows field labels without help text link" do + edit_dialog.expect_title section.name + + edit_dialog.expect_field_label_without_help_text "Multi list field" + edit_dialog.expect_field_label_without_help_text "Multi version field" + edit_dialog.expect_field_label_without_help_text "Multi user field" + end + end + + context "with attribute help texts defined" do + let!(:multi_list_help_text) do + create(:project_help_text, attribute_name: multi_list_project_custom_field.attribute_name) + end + let!(:multi_version_help_text) do + create(:project_help_text, attribute_name: multi_version_project_custom_field.attribute_name) + end + let!(:multi_user_help_text) do + create(:project_help_text, attribute_name: multi_user_project_custom_field.attribute_name) + end + + before do + overview_page.open_edit_dialog_for_section(section) + end + + it "shows field labels with help text link" do + edit_dialog.expect_title section.name + + edit_dialog.expect_field_label_with_help_text "Multi list field" + edit_dialog.expect_field_label_with_help_text "Multi version field" + edit_dialog.expect_field_label_with_help_text "Multi user field" + end + + it "shows help text modal on clicking help text link" do + edit_dialog.expect_title section.name + + edit_dialog.click_help_text_link_for_label "Multi list field" + + expect(page).to have_modal "Multi list field" + within_modal "Multi list field" do + expect(page).to have_text "Attribute help text" + + click_on "Close" + end + expect(page).to have_no_modal "Multi list field" + end + end + end +end diff --git a/spec/forms/custom_fields/inputs/bool_spec.rb b/spec/forms/custom_fields/inputs/bool_spec.rb new file mode 100644 index 00000000000..7d248ac8ce2 --- /dev/null +++ b/spec/forms/custom_fields/inputs/bool_spec.rb @@ -0,0 +1,61 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) the OpenProject GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See COPYRIGHT and LICENSE files for more details. +#++ +# +require "spec_helper" + +RSpec.describe CustomFields::Inputs::Bool, type: :forms do + include_context "with rendered custom field input form" + + let(:custom_field) { create(:boolean_project_custom_field, name: "Boolean field") } + + it_behaves_like "rendering label with help text", "Boolean field" + + context "without a value" do + it "renders field" do + expect(rendered_form).to have_unchecked_field "Boolean field", with: "1" + end + end + + context "when value is true" do + let(:value) { true } + + it "renders field" do + expect(rendered_form).to have_checked_field "Boolean field", with: "1" + end + end + + context "when value is false" do + let(:value) { false } + + it "renders field" do + expect(rendered_form).to have_unchecked_field "Boolean field", with: "1" + end + end +end diff --git a/spec/forms/custom_fields/inputs/date_spec.rb b/spec/forms/custom_fields/inputs/date_spec.rb new file mode 100644 index 00000000000..e6845d3971a --- /dev/null +++ b/spec/forms/custom_fields/inputs/date_spec.rb @@ -0,0 +1,65 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) the OpenProject GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See COPYRIGHT and LICENSE files for more details. +#++ +# +require "spec_helper" + +RSpec.describe CustomFields::Inputs::Date, type: :forms do + include_context "with rendered custom field input form" + + let(:custom_field) { create(:date_project_custom_field, name: "Date field") } + + it_behaves_like "rendering label with help text", "Date field" + + context "without a value" do + it "renders field" do + expect(rendered_form).to have_field "Date field", type: :date, with: "" + end + end + + context "when value is invalid" do + let(:value) { "NOT A DATE" } + + it "renders invalid field" do + expect(rendered_form).to have_field "Date field", type: :date, with: "NOT A DATE", aria: { invalid: true } + end + + it "renders error message" do + expect(rendered_form).to have_css ".FormControl-inlineValidation", text: "Value is not a valid date." + end + end + + context "when value is valid" do + let(:value) { Date.civil(2024, 3, 20) } + + it "renders field" do + expect(rendered_form).to have_field "Date field", type: :date, with: "2024-03-20" + end + end +end diff --git a/spec/forms/custom_fields/inputs/float_spec.rb b/spec/forms/custom_fields/inputs/float_spec.rb new file mode 100644 index 00000000000..258f1f61c0b --- /dev/null +++ b/spec/forms/custom_fields/inputs/float_spec.rb @@ -0,0 +1,53 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) the OpenProject GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See COPYRIGHT and LICENSE files for more details. +#++ +# +require "spec_helper" + +RSpec.describe CustomFields::Inputs::Float, type: :forms do + include_context "with rendered custom field input form" + + let(:custom_field) { create(:float_project_custom_field, name: "Float field") } + + it_behaves_like "rendering label with help text", "Float field" + + context "without a value" do + it "renders field" do + expect(rendered_form).to have_field "Float field", type: :number, with: "" + end + end + + context "with a value" do + let(:value) { 78.23 } + + it "renders field" do + expect(rendered_form).to have_field "Float field", type: :number, with: "78.23" + end + end +end diff --git a/spec/forms/custom_fields/inputs/int_spec.rb b/spec/forms/custom_fields/inputs/int_spec.rb new file mode 100644 index 00000000000..2b623b0e0d9 --- /dev/null +++ b/spec/forms/custom_fields/inputs/int_spec.rb @@ -0,0 +1,53 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) the OpenProject GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See COPYRIGHT and LICENSE files for more details. +#++ +# +require "spec_helper" + +RSpec.describe CustomFields::Inputs::Int, type: :forms do + include_context "with rendered custom field input form" + + let(:custom_field) { create(:integer_project_custom_field, name: "Integer field") } + + it_behaves_like "rendering label with help text", "Integer field" + + context "without a value" do + it "renders field" do + expect(rendered_form).to have_field "Integer field", type: :number, with: "" + end + end + + context "with a value" do + let(:value) { 76 } + + it "renders field" do + expect(rendered_form).to have_field "Integer field", type: :number, with: "76" + end + end +end diff --git a/spec/forms/custom_fields/inputs/multi_select_list_spec.rb b/spec/forms/custom_fields/inputs/multi_select_list_spec.rb new file mode 100644 index 00000000000..dd7a6cff0e5 --- /dev/null +++ b/spec/forms/custom_fields/inputs/multi_select_list_spec.rb @@ -0,0 +1,54 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) the OpenProject GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See COPYRIGHT and LICENSE files for more details. +#++ +# +require "spec_helper" + +RSpec.describe CustomFields::Inputs::MultiSelectList, type: :forms do + include_context "with rendered custom field input form" + + let(:custom_field) do + create( + :list_project_custom_field, + name: "Multi-list field", + multi_value: true, + possible_values: ["uno", "due", "tre", "quattro"] + ) + end + let(:value) { custom_field.possible_values.last(2).pluck(:id) } + + it_behaves_like "rendering label with help text", "Multi-list field" + it_behaves_like "rendering autocompleter", "Multi-list field", multiple: true do + it "sets correct autocompleter inputs" do + expect(autocompleter["data-items"]).to have_json_size(4) + expect(autocompleter["data-model"]).to have_json_size(2) + expect(autocompleter["data-model"]).to be_json_eql(%{[{"name": "tre"}, {"name": "quattro"}]}) + end + end +end diff --git a/spec/forms/custom_fields/inputs/multi_user_select_list_spec.rb b/spec/forms/custom_fields/inputs/multi_user_select_list_spec.rb new file mode 100644 index 00000000000..6e529144075 --- /dev/null +++ b/spec/forms/custom_fields/inputs/multi_user_select_list_spec.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) the OpenProject GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See COPYRIGHT and LICENSE files for more details. +#++ +# +require "spec_helper" + +RSpec.describe CustomFields::Inputs::MultiUserSelectList, type: :forms do + include_context "with rendered custom field input form" + + let(:custom_field) { create(:user_project_custom_field, name: "Users field", multi_value: true) } + let(:value) { create_list(:user, 2) } + + it_behaves_like "rendering label with help text", "Users field" + it_behaves_like "rendering autocompleter", "Users field", tag_name: "opce-user-autocompleter", multiple: true do + it "sets correct autocompleter inputs" do + expect(autocompleter["data-resource"]).to be_json_eql(%{"principals"}) + expect(autocompleter["data-url"]).to be_json_eql(%{"/api/v3/principals"}) + expect(autocompleter["data-input-value"]).to have_json_size(2) + expect(autocompleter["data-input-value"]).to be_json_eql(value.pluck(:id).map(&:to_s).to_json) + end + end +end diff --git a/spec/forms/custom_fields/inputs/multi_version_select_list_spec.rb b/spec/forms/custom_fields/inputs/multi_version_select_list_spec.rb new file mode 100644 index 00000000000..36f7dfe86b0 --- /dev/null +++ b/spec/forms/custom_fields/inputs/multi_version_select_list_spec.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) the OpenProject GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See COPYRIGHT and LICENSE files for more details. +#++ +# +require "spec_helper" + +RSpec.describe CustomFields::Inputs::MultiVersionSelectList, type: :forms do + include_context "with rendered custom field input form" + + let(:custom_field) { create(:version_project_custom_field, name: "Versions field", multi_value: true) } + let(:value) { create_list(:version, 2, project: model) } + let!(:other_versions) { create_list(:version, 3, project: model) } + + it_behaves_like "rendering label with help text", "Versions field" + it_behaves_like "rendering autocompleter", "Versions field", multiple: true do + it "sets correct autocompleter inputs" do + expect(autocompleter["data-items"]).to have_json_size(5) + expect(autocompleter["data-model"]).to have_json_size(2) + expect(autocompleter["data-model"]).to be_json_eql(value.map { it.slice(:name) }.to_json).excluding("group_by") + end + end +end diff --git a/spec/forms/custom_fields/inputs/single_select_list_spec.rb b/spec/forms/custom_fields/inputs/single_select_list_spec.rb new file mode 100644 index 00000000000..3057f7f8916 --- /dev/null +++ b/spec/forms/custom_fields/inputs/single_select_list_spec.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) the OpenProject GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See COPYRIGHT and LICENSE files for more details. +#++ +# +require "spec_helper" + +RSpec.describe CustomFields::Inputs::SingleSelectList, type: :forms do + include_context "with rendered custom field input form" + + let(:custom_field) { create(:list_project_custom_field, name: "List field", possible_values: ["eins", "zwei", "drei"]) } + let(:value) { custom_field.possible_values.first.id } + + it_behaves_like "rendering label with help text", "List field" + it_behaves_like "rendering autocompleter", "List field" do + it "sets correct autocompleter inputs" do + expect(autocompleter["data-items"]).to have_json_size(3) + expect(autocompleter["data-model"]).to be_json_eql(%{{"name": "eins"}}) + end + end +end diff --git a/spec/forms/custom_fields/inputs/single_user_select_list_spec.rb b/spec/forms/custom_fields/inputs/single_user_select_list_spec.rb new file mode 100644 index 00000000000..66d4498b2c2 --- /dev/null +++ b/spec/forms/custom_fields/inputs/single_user_select_list_spec.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) the OpenProject GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See COPYRIGHT and LICENSE files for more details. +#++ +# +require "spec_helper" + +RSpec.describe CustomFields::Inputs::SingleUserSelectList, type: :forms do + include_context "with rendered custom field input form" + + let(:custom_field) { create(:user_project_custom_field, name: "User field") } + let(:value) { create(:user) } + + it_behaves_like "rendering label with help text", "User field" + it_behaves_like "rendering autocompleter", "User field", tag_name: "opce-user-autocompleter" do + it "sets correct autocompleter inputs" do + expect(autocompleter["data-resource"]).to be_json_eql(%{"principals"}) + expect(autocompleter["data-url"]).to be_json_eql(%{"/api/v3/principals"}) + expect(autocompleter["data-input-value"]).to be_json_eql(%{"#{value.id}"}) + end + end +end diff --git a/spec/forms/custom_fields/inputs/single_version_select_list_spec.rb b/spec/forms/custom_fields/inputs/single_version_select_list_spec.rb new file mode 100644 index 00000000000..999e9aafe58 --- /dev/null +++ b/spec/forms/custom_fields/inputs/single_version_select_list_spec.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) the OpenProject GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See COPYRIGHT and LICENSE files for more details. +#++ +# +require "spec_helper" + +RSpec.describe CustomFields::Inputs::SingleVersionSelectList, type: :forms do + include_context "with rendered custom field input form" + + let(:custom_field) { create(:version_project_custom_field, name: "Version field") } + let(:value) { create(:version, name: "Version 26", project: model) } + + it_behaves_like "rendering label with help text", "Version field" + it_behaves_like "rendering autocompleter", "Version field" do + it "sets correct autocompleter inputs" do + expect(autocompleter["data-items"]).to have_json_size(1) + expect(autocompleter["data-model"]).to be_json_eql(%{{"name":"Version 26"}}).excluding("group_by") + end + end +end diff --git a/spec/forms/custom_fields/inputs/string_spec.rb b/spec/forms/custom_fields/inputs/string_spec.rb new file mode 100644 index 00000000000..875cac399a3 --- /dev/null +++ b/spec/forms/custom_fields/inputs/string_spec.rb @@ -0,0 +1,89 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) the OpenProject GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See COPYRIGHT and LICENSE files for more details. +#++ +# +require "spec_helper" + +RSpec.describe CustomFields::Inputs::String, type: :forms do + include_context "with rendered custom field input form" + + context "with a string custom field" do + let(:custom_field) { create(:string_project_custom_field, name: "String field") } + + it_behaves_like "rendering label with help text", "String field" + + context "without a value" do + it "renders field" do + expect(rendered_form).to have_field "String field", type: :text, with: "" + end + end + + context "when value is empty" do + let(:value) { "" } + + it "renders field" do + expect(rendered_form).to have_field "String field", type: :text, with: "" + end + end + + context "when value is present" do + let(:value) { "weil wir es uns wert sind" } + + it "renders field" do + expect(rendered_form).to have_field "String field", type: :text, with: "weil wir es uns wert sind" + end + end + end + + context "with a link custom field" do + let(:custom_field) { create(:link_project_custom_field, name: "Link field") } + + it_behaves_like "rendering label with help text", "Link field" + + context "when value is invalid" do + let(:value) { "!@£$ NOT A LINK" } + + it "renders invalid field" do + expect(rendered_form).to have_field "Link field", type: :text, with: "!@£$ NOT A LINK", aria: { invalid: true } + end + + it "renders error message" do + expect(rendered_form).to have_css ".FormControl-inlineValidation", text: "Value is not a valid URL." + end + end + + context "when value is present" do + let(:value) { "https://developer.mozilla.org/en-US/docs/" } + + it "renders field" do + expect(rendered_form).to have_field "Link field", type: :text, with: "https://developer.mozilla.org/en-US/docs/" + end + end + end +end diff --git a/spec/forms/custom_fields/inputs/text_spec.rb b/spec/forms/custom_fields/inputs/text_spec.rb new file mode 100644 index 00000000000..2ec35fd6b11 --- /dev/null +++ b/spec/forms/custom_fields/inputs/text_spec.rb @@ -0,0 +1,61 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) the OpenProject GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See COPYRIGHT and LICENSE files for more details. +#++ +# +require "spec_helper" + +RSpec.describe CustomFields::Inputs::Text, type: :forms do + include_context "with rendered custom field input form" + + let(:custom_field) { create(:text_project_custom_field, name: "Text field") } + + it_behaves_like "rendering label with help text", "Text field" + + context "without a value" do + it "renders field" do + expect(rendered_form).to have_field "Text field", type: :textarea, with: "", visible: :hidden + end + end + + context "when value is empty" do + let(:value) { "" } + + it "renders field" do + expect(rendered_form).to have_field "Text field", type: :textarea, with: "", visible: :hidden + end + end + + context "when value is present" do + let(:value) { "parce que nous le valons bien" } + + it "renders field" do + expect(rendered_form).to have_field "Text field", type: :textarea, with: "parce que nous le valons bien", visible: :hidden + end + end +end diff --git a/spec/lib/primer/open_project/forms/dsl/input_methods_spec.rb b/spec/lib/primer/open_project/forms/dsl/input_methods_spec.rb new file mode 100644 index 00000000000..b67f2856093 --- /dev/null +++ b/spec/lib/primer/open_project/forms/dsl/input_methods_spec.rb @@ -0,0 +1,250 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) the OpenProject GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See COPYRIGHT and LICENSE files for more details. +#++ +# +require "spec_helper" + +RSpec.describe Primer::OpenProject::Forms::Dsl::InputMethods, type: :forms do + let(:form_object) { Primer::Forms::Dsl::FormObject.extend(described_class) } + let(:builder) { instance_double(ActionView::Helpers::FormBuilder, object: model) } + let(:form) { instance_double(ApplicationForm, model:, caption_template?: false) } + let(:form_dsl) { form_object.new(builder:, form:) } + + let(:name) { :subject } + let(:label) { "Subject" } + let(:options) { {} } + + let(:model) { build_stubbed(:project) } + + subject(:field) { field_group.first } + + before do + allow(form).to receive(:wrap_attribute_label_with_help_text) do |label, name| + "#{label} " + end + end + + shared_examples_for "input class" do |input_class| + it "instantiates correct input class" do + expect(field).to be_a(input_class) + end + end + + shared_examples_for "supporting help texts" do + context "when include_help_text: option is true (default)" do + context "when no additional help_text_options: are passed" do + it "wraps the label with help text" do + expect(field.label).to start_with(label) + .and end_with("") + end + end + + context "when additional help_text_options: are passed" do + let(:attribute_name) { :subject_attribute } + let(:options) { { help_text_options: { attribute_name: } } } + + it "wraps the label with help text" do + expect(field.label).to start_with(label) + .and end_with("") + end + end + end + + context "when include_help_text: option is false" do + let(:options) { { include_help_text: false } } + + it "does not wrap the label" do + expect(field.label).to eq label + end + end + end + + describe "multi input methods" do + describe "#multi" do + let(:field_group) { form_dsl.multi(name:, label:, **options) } + + include_examples "input class", Primer::Forms::Dsl::MultiInput + it_behaves_like "supporting help texts" + end + + describe "#check_box" do + let(:field_group) { form_dsl.check_box(name:, label:, **options) } + + include_examples "input class", Primer::Forms::Dsl::CheckBoxInput + it_behaves_like "supporting help texts" + end + + describe "#radio_button_group" do + let(:field_group) { form_dsl.radio_button_group(name:, label:, **options) } + + include_examples "input class", Primer::Forms::Dsl::RadioButtonGroupInput + it_behaves_like "supporting help texts" + end + + describe "#check_box_group" do + let(:field_group) { form_dsl.check_box_group(name:, label:, **options) } + + include_examples "input class", Primer::Forms::Dsl::CheckBoxGroupInput + it_behaves_like "supporting help texts" + end + end + + describe "#separator" do + let(:field_group) { form_dsl.separator } + + include_examples "input class", Primer::Forms::Separator + end + + describe "text input methods" do + describe "#text_field" do + let(:field_group) { form_dsl.text_field(name:, label:, **options) } + + include_examples "input class", Primer::Forms::Dsl::TextFieldInput + it_behaves_like "supporting help texts" + end + + describe "#auto_complete" do + let(:field_group) { form_dsl.auto_complete(name:, label:, **options) } + + include_examples "input class", Primer::Forms::Dsl::AutoCompleteInput + it_behaves_like "supporting help texts" + end + + describe "#text_area" do + let(:field_group) { form_dsl.text_area(name:, label:, **options) } + + include_examples "input class", Primer::Forms::Dsl::TextAreaInput + it_behaves_like "supporting help texts" + end + end + + describe "select input methods" do + describe "#select_list" do + let(:field_group) { form_dsl.select_list(name:, label:, **options) } + + include_examples "input class", Primer::Forms::Dsl::SelectInput + it_behaves_like "supporting help texts" + end + + describe "#action_menu" do + let(:field_group) { form_dsl.action_menu(name:, label:, **options) } + + include_examples "input class", Primer::Forms::Dsl::ActionMenuInput + it_behaves_like "supporting help texts" + end + end + + describe "button input methods" do + describe "#submit" do + let(:field_group) { form_dsl.submit(name:, label:, **options) } + + include_examples "input class", Primer::Forms::Dsl::SubmitButtonInput + it_behaves_like "supporting help texts" + end + + describe "#button" do + let(:field_group) { form_dsl.button(name:, label:, **options) } + + include_examples "input class", Primer::Forms::Dsl::ButtonInput + it_behaves_like "supporting help texts" + end + end + + describe "OpenProject input methods" do + describe "#autocompleter" do + let(:field_group) { form_dsl.autocompleter(name:, label:, autocomplete_options: {}, **options) } + + include_examples "input class", Primer::OpenProject::Forms::Dsl::AutocompleterInput + it_behaves_like "supporting help texts" + end + + describe "#pattern_input" do + let(:field_group) { form_dsl.pattern_input(name:, label:, value: "", suggestions: [], **options) } + + include_examples "input class", Primer::OpenProject::Forms::Dsl::PatternInput + it_behaves_like "supporting help texts" + end + + describe "#color_select_list" do + let(:field_group) { form_dsl.color_select_list(name:, label:, **options) } + + include_examples "input class", Primer::OpenProject::Forms::Dsl::ColorSelectInput + it_behaves_like "supporting help texts" + end + + describe "#html_content" do + let(:field_group) { form_dsl.html_content(name:, label:, **options) } + + include_examples "input class", Primer::OpenProject::Forms::Dsl::HtmlContentInput + end + + describe "#project_autocompleter" do + let(:field_group) { form_dsl.project_autocompleter(name:, label:, autocomplete_options: {}, **options) } + + include_examples "input class", Primer::OpenProject::Forms::Dsl::ProjectAutocompleterInput + it_behaves_like "supporting help texts" + end + + describe "#single_date_picker" do + let(:field_group) { form_dsl.single_date_picker(name:, label:, datepicker_options: {}, **options) } + + include_examples "input class", Primer::OpenProject::Forms::Dsl::SingleDatePickerInput + it_behaves_like "supporting help texts" + end + + describe "#range_date_picker" do + let(:field_group) { form_dsl.range_date_picker(name:, label:, datepicker_options: {}, **options) } + + include_examples "input class", Primer::OpenProject::Forms::Dsl::RangeDatePickerInput + it_behaves_like "supporting help texts" + end + + describe "#rich_text_area" do + let(:field_group) { form_dsl.rich_text_area(name:, label:, rich_text_options: {}, **options) } + + include_examples "input class", Primer::OpenProject::Forms::Dsl::RichTextAreaInput + it_behaves_like "supporting help texts" + end + + describe "#storage_manual_project_folder_selection" do + let(:project_storage) { build_stubbed(:project_storage) } + let(:field_group) { form_dsl.storage_manual_project_folder_selection(name:, label:, project_storage:, **options) } + + include_examples "input class", Primer::OpenProject::Forms::Dsl::StorageManualProjectFolderSelectionInput + it_behaves_like "supporting help texts" + end + + describe "#work_package_autocompleter" do + let(:field_group) { form_dsl.work_package_autocompleter(name:, label:, autocomplete_options: {}, **options) } + + include_examples "input class", Primer::OpenProject::Forms::Dsl::WorkPackageAutocompleterInput + it_behaves_like "supporting help texts" + end + end +end diff --git a/spec/support/components/projects/project_custom_fields/edit_dialog.rb b/spec/support/components/projects/project_custom_fields/edit_dialog.rb index 4d76425893e..910bb958989 100644 --- a/spec/support/components/projects/project_custom_fields/edit_dialog.rb +++ b/spec/support/components/projects/project_custom_fields/edit_dialog.rb @@ -95,6 +95,33 @@ module Components expect(page).to have_css(async_content_container_css_selector) end + def expect_field_label_with_help_text(label_text) + expect_field_label(label_text) + expect(find_field_label(label_text)).to have_link accessible_name: "Show help text" + end + + def expect_field_label_without_help_text(label_text) + expect_field_label(label_text) + expect(find_field_label(label_text)).to have_no_link accessible_name: "Show help text" + end + + def click_help_text_link_for_label(label_text) + link = find_field_label(label_text).find(:link, accessible_name: "Show help text") + link.click + end + + def expect_field_label(label_text) + within_dialog do + expect(page).to have_element :label, text: label_text + end + end + + def find_field_label(label_text) + within_dialog do + page.find(:element, :label, text: label_text) + end + end + ### def input_containers diff --git a/spec/support/forms/rendered_custom_field_input_form.rb b/spec/support/forms/rendered_custom_field_input_form.rb new file mode 100644 index 00000000000..6030225210a --- /dev/null +++ b/spec/support/forms/rendered_custom_field_input_form.rb @@ -0,0 +1,99 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) the OpenProject GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See COPYRIGHT and LICENSE files for more details. +#++ +RSpec.shared_context "with rendered custom field input form" do + include ViewComponent::TestHelpers + + let(:model) { create(:project) } + let!(:custom_field_mapping) do + create(:project_custom_field_project_mapping, project: model, project_custom_field: custom_field) + end + let(:value) { nil } + + current_user { build_stubbed(:admin) } + + def build_form(builder) + described_class.new(builder, custom_field:, object: model) + end + + def render_form + render_in_view_context(model, self) do |model, spec_context| + primer_form_with(url: "/foo", model:) do |f| + render(spec_context.build_form(f)) + end + end + end + + before do + model.custom_field_values = { "#{custom_field.id}": value } if value + model.custom_field_values.first.valid? + end + + subject(:rendered_form) do + render_form + page + end + + shared_examples "rendering label" do |label_text| + it "renders a label" do + expect(rendered_form).to have_element :label, text: label_text + end + end + + shared_examples "rendering autocompleter" do |label_text, tag_name: "opce-autocompleter", multiple: false| + let(:label_id) { rendered_form.find(:element, :label, text: label_text)["for"] } + let(:autocompleter) { rendered_form.find(:element, tag_name, "data-label-for-id": "\"#{label_id}\"") } + + it "renders autocompleter field" do + expect(rendered_form).to have_element tag_name, "data-label-for-id": "\"#{label_id}\"" do |autocompleter| + expect(autocompleter["data-multiple"]).to be_json_eql(multiple) + end + end + end + + shared_examples "rendering label with help text" do |label_text| + let(:label) { rendered_form.find(:element, :label, text: label_text) } + + include_examples "rendering label", label_text + + context "without attribute help text" do + it "does not render help text link" do + expect(label).to have_no_link class: "op-attribute-help-text" + end + end + + context "with attribute help text" do + let!(:attribute_help_text) { create(:project_help_text, attribute_name: custom_field.attribute_name) } + + it "renders help text link" do + expect(label).to have_link class: "op-attribute-help-text" + end + end + end +end