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