From c29029e0d8a66bb62db115c46c0ee072aa76bd99 Mon Sep 17 00:00:00 2001 From: Andreas Pfohl Date: Thu, 26 Sep 2024 13:58:59 +0200 Subject: [PATCH 1/4] [58105] Added HierarchyItemService with initialize contract --- .../service_initialization_contract.rb | 43 +++++++++++++++++ .../hierarchy/hierarchical_item_service.rb | 46 +++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 app/contracts/custom_fields/hierarchy/service_initialization_contract.rb create mode 100644 app/services/custom_fields/hierarchy/hierarchical_item_service.rb diff --git a/app/contracts/custom_fields/hierarchy/service_initialization_contract.rb b/app/contracts/custom_fields/hierarchy/service_initialization_contract.rb new file mode 100644 index 00000000000..95995bc8d6d --- /dev/null +++ b/app/contracts/custom_fields/hierarchy/service_initialization_contract.rb @@ -0,0 +1,43 @@ +# 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. +#++ + +module CustomFields + module Hierarchy + class ServiceInitializationContract < Dry::Validation::Contract + params do + required(:field_format).filled(:string) + end + + rule(:field_format) do + key.failure("Custom field must have field format 'hierarchy'") unless value == "hierarchy" + end + end + end +end diff --git a/app/services/custom_fields/hierarchy/hierarchical_item_service.rb b/app/services/custom_fields/hierarchy/hierarchical_item_service.rb new file mode 100644 index 00000000000..c33b81d0da2 --- /dev/null +++ b/app/services/custom_fields/hierarchy/hierarchical_item_service.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. +#++ + +module CustomFields + module Hierarchy + class HierarchicalItemService + def initialize(custom_field) + @custom_field = custom_field + + contract = ServiceInitializationContract.new + result = contract.call(custom_field) + + if result.failure? + raise ArgumentError, "Invalid custom field: #{result.errors.to_h}" + end + end + end + end +end From 26c8e4889c705111093f2f90c88e8278a43f270d Mon Sep 17 00:00:00 2001 From: Andreas Pfohl Date: Wed, 2 Oct 2024 14:16:28 +0200 Subject: [PATCH 2/4] [58105] Added generate_root and insert_item to HierarchicalItemService --- .../hierarchy/generate_root_contract.rb | 43 +++++++ .../hierarchy/insert_item_contract.rb | 57 +++++++++ .../hierarchy/hierarchical_item_service.rb | 43 ++++++- .../hierarchy/generate_root_contract_spec.rb | 78 ++++++++++++ .../hierarchy/insert_item_contract_spec.rb | 119 ++++++++++++++++++ .../service_initialization_contract_spec.rb | 97 ++++++++++++++ spec/factories/hierarchy_item_factory.rb | 7 ++ .../hierarchical_item_service_spec.rb | 98 +++++++++++++++ 8 files changed, 537 insertions(+), 5 deletions(-) create mode 100644 app/contracts/custom_fields/hierarchy/generate_root_contract.rb create mode 100644 app/contracts/custom_fields/hierarchy/insert_item_contract.rb create mode 100644 spec/contracts/custom_fields/hierarchy/generate_root_contract_spec.rb create mode 100644 spec/contracts/custom_fields/hierarchy/insert_item_contract_spec.rb create mode 100644 spec/contracts/custom_fields/hierarchy/service_initialization_contract_spec.rb create mode 100644 spec/factories/hierarchy_item_factory.rb create mode 100644 spec/services/custom_fields/hierarchy/hierarchical_item_service_spec.rb diff --git a/app/contracts/custom_fields/hierarchy/generate_root_contract.rb b/app/contracts/custom_fields/hierarchy/generate_root_contract.rb new file mode 100644 index 00000000000..4e993e5f5b4 --- /dev/null +++ b/app/contracts/custom_fields/hierarchy/generate_root_contract.rb @@ -0,0 +1,43 @@ +# 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. +#++ + +module CustomFields + module Hierarchy + class GenerateRootContract < Dry::Validation::Contract + params do + required(:hierarchy_root) + end + + rule(:hierarchy_root) do + key.failure("Hierarchical root already set") unless value.nil? + end + end + end +end diff --git a/app/contracts/custom_fields/hierarchy/insert_item_contract.rb b/app/contracts/custom_fields/hierarchy/insert_item_contract.rb new file mode 100644 index 00000000000..57d5e771480 --- /dev/null +++ b/app/contracts/custom_fields/hierarchy/insert_item_contract.rb @@ -0,0 +1,57 @@ +# 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. +#++ + +module CustomFields + module Hierarchy + class InsertItemContract < Dry::Validation::Contract + params do + required(:parent).filled + required(:label).filled(:string) + optional(:short).filled(:string) + end + + rule(:parent) do + if value.is_a?(CustomField::Hierarchy::Item) + unless value.persisted? + key.failure("Parent must exist") + end + else + key.failure("Parent must be of type 'Item'") + end + end + + rule(:label) do + if CustomField::Hierarchy::Item.exists?(parent_id: values[:parent], label: value) + key.failure("Label must be unique within the same hierarchy level") + end + end + end + end +end diff --git a/app/services/custom_fields/hierarchy/hierarchical_item_service.rb b/app/services/custom_fields/hierarchy/hierarchical_item_service.rb index c33b81d0da2..8ec7940fc0b 100644 --- a/app/services/custom_fields/hierarchy/hierarchical_item_service.rb +++ b/app/services/custom_fields/hierarchy/hierarchical_item_service.rb @@ -31,15 +31,48 @@ module CustomFields module Hierarchy class HierarchicalItemService + include Dry::Monads[:result] + def initialize(custom_field) + validation = ServiceInitializationContract.new.call(field_format: custom_field.field_format) + # rubocop:disable Rails/DeprecatedActiveModelErrorsMethods + raise ArgumentError, "Invalid custom field: #{validation.errors.to_h}" if validation.failure? + # rubocop:enable Rails/DeprecatedActiveModelErrorsMethods + @custom_field = custom_field + end - contract = ServiceInitializationContract.new - result = contract.call(custom_field) + def generate_root + CustomFields::Hierarchy::GenerateRootContract + .new + .call(hierarchy_root: @custom_field.hierarchy_root) + .to_monad + .bind { create_root_item } + end - if result.failure? - raise ArgumentError, "Invalid custom field: #{result.errors.to_h}" - end + def insert_item(parent:, label:, short: nil) + CustomFields::Hierarchy::InsertItemContract + .new + .call(parent:, label:, short:) + .to_monad + .bind { |validation| create_child_item(validation) } + end + + private + + def create_root_item + item = CustomField::Hierarchy::Item.create(custom_field: @custom_field) + return Failure(item.errors) unless item.persisted? + + Success(item) + end + + def create_child_item(validation) + item = CustomField::Hierarchy::Item + .create(parent: validation[:parent], label: validation[:label], short: validation[:short]) + return Failure(item.errors) unless item.persisted? + + Success(item) end end end diff --git a/spec/contracts/custom_fields/hierarchy/generate_root_contract_spec.rb b/spec/contracts/custom_fields/hierarchy/generate_root_contract_spec.rb new file mode 100644 index 00000000000..78429458a2d --- /dev/null +++ b/spec/contracts/custom_fields/hierarchy/generate_root_contract_spec.rb @@ -0,0 +1,78 @@ +# 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 "rails_helper" + +RSpec.describe CustomFields::Hierarchy::GenerateRootContract do + subject { described_class.new } + + describe "#call" do + context "when hierarchy_root is nil" do + let(:custom_field) { create(:custom_field, field_format: "hierarchy", hierarchy_root: nil) } + + it "is valid" do + result = subject.call(hierarchy_root: custom_field.hierarchy_root) + expect(result).to be_success + end + end + + context "when hierarchy_root is not nil" do + let(:hierarchy_root) { create(:hierarchy_item) } + let(:custom_field) { create(:custom_field, field_format: "hierarchy", hierarchy_root:) } + + it "is invalid" do + result = subject.call(hierarchy_root: custom_field.hierarchy_root) + expect(result).to be_failure + # rubocop:disable Rails/DeprecatedActiveModelErrorsMethods + expect(result.errors.to_h).to include(hierarchy_root: ["Hierarchical root already set"]) + # rubocop:enable Rails/DeprecatedActiveModelErrorsMethods + end + end + + context "when inputs are valid" do + it "creates a success result" do + [ + { hierarchy_root: nil } + ].each { |params| expect(subject.call(params)).to be_success } + end + end + + context "when inputs are invalid" do + it "creates a failure result" do + [ + {}, + { hierarchy_root: create(:hierarchy_item) }, + { hierarchy_root: "" }, + { hierarchy_root: 42 } + ].each { |params| expect(subject.call(params)).to be_failure } + end + end + end +end diff --git a/spec/contracts/custom_fields/hierarchy/insert_item_contract_spec.rb b/spec/contracts/custom_fields/hierarchy/insert_item_contract_spec.rb new file mode 100644 index 00000000000..70af1da8caa --- /dev/null +++ b/spec/contracts/custom_fields/hierarchy/insert_item_contract_spec.rb @@ -0,0 +1,119 @@ +# 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 "rails_helper" + +RSpec.describe CustomFields::Hierarchy::InsertItemContract do + subject { described_class.new } + + # rubocop:disable Rails/DeprecatedActiveModelErrorsMethods + describe "#call" do + let(:parent) { create(:hierarchy_item) } + + context "when all required fields are valid" do + let(:params) { { parent:, label: "Valid Label" } } + + it "is valid" do + result = subject.call(params) + expect(result).to be_success + end + end + + context "when parent is not of type 'Item'" do + let(:invalid_parent) { create(:custom_field) } + let(:params) { { parent: invalid_parent, label: "Valid Label" } } + + it "is invalid" do + result = subject.call(params) + expect(result).to be_failure + expect(result.errors.to_h).to include(parent: ["Parent must be of type 'Item'"]) + end + end + + context "when label is not unique within the same hierarchy level" do + before do + create(:hierarchy_item, parent:, label: "Duplicate Label") + end + + let(:params) { { parent:, label: "Duplicate Label" } } + + it "is invalid" do + result = subject.call(params) + expect(result).to be_failure + expect(result.errors.to_h).to include(label: ["Label must be unique within the same hierarchy level"]) + end + end + + context "when short is set and is a string" do + let(:params) { { parent:, label: "Valid Label", short: "Valid Short" } } + + it "is valid" do + result = subject.call(params) + expect(result).to be_success + end + end + + context "when short is set and is not a string" do + let(:params) { { parent:, label: "Valid Label", short: 123 } } + + it "is invalid" do + result = subject.call(params) + expect(result).to be_failure + expect(result.errors.to_h).to include(short: ["must be a string"]) + end + end + + context "when inputs are valid" do + it "creates a success result" do + [ + { parent:, label: "A label", short: "A shorthand" }, + { parent:, label: "A label" } + ].each { |params| expect(subject.call(params)).to be_success } + end + end + + context "when inputs are invalid" do + it "creates a failure result" do + [ + { parent:, label: "A label", short: "" }, + { parent:, label: "A label", short: nil }, + { parent:, label: "" }, + { parent:, label: nil }, + { parent: }, + { parent: nil }, + { parent: nil, label: "A label" }, + { parent: "parent", label: "A label" }, + { parent: 42, label: "A label" } + ].each { |params| expect(subject.call(params)).to be_failure } + end + end + end + # rubocop:enable Rails/DeprecatedActiveModelErrorsMethods +end diff --git a/spec/contracts/custom_fields/hierarchy/service_initialization_contract_spec.rb b/spec/contracts/custom_fields/hierarchy/service_initialization_contract_spec.rb new file mode 100644 index 00000000000..2cf1979cc78 --- /dev/null +++ b/spec/contracts/custom_fields/hierarchy/service_initialization_contract_spec.rb @@ -0,0 +1,97 @@ +# 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 "rails_helper" + +RSpec.describe CustomFields::Hierarchy::ServiceInitializationContract do + subject { described_class.new } + + # rubocop:disable Rails/DeprecatedActiveModelErrorsMethods + describe "#call" do + context "when field_format is 'hierarchy'" do + let(:params) { { field_format: "hierarchy" } } + + it "is valid" do + result = subject.call(params) + expect(result).to be_success + end + end + + context "when field_format is not 'hierarchy'" do + let(:params) { { field_format: "text" } } + + it "is invalid" do + result = subject.call(params) + expect(result).to be_failure + expect(result.errors.to_h).to include(field_format: ["Custom field must have field format 'hierarchy'"]) + end + end + + context "when field_format is missing" do + let(:params) { {} } + + it "is invalid" do + result = subject.call(params) + expect(result).to be_failure + expect(result.errors.to_h).to include(field_format: ["is missing"]) + end + end + + context "when field_format is nil" do + let(:params) { { field_format: nil } } + + it "is invalid" do + result = subject.call(params) + expect(result).to be_failure + expect(result.errors.to_h).to include(field_format: ["must be filled"]) + end + end + + context "when inputs are valid" do + it "creates a success result" do + [ + { field_format: "hierarchy" } + ].each { |params| expect(subject.call(params)).to be_success } + end + end + + context "when inputs are invalid" do + it "creates a failure result" do + [ + {}, + { field_format: "text" }, + { field_format: nil }, + { field_format: 42 } + ].each { |params| expect(subject.call(params)).to be_failure } + end + end + end + # rubocop:enable Rails/DeprecatedActiveModelErrorsMethods +end diff --git a/spec/factories/hierarchy_item_factory.rb b/spec/factories/hierarchy_item_factory.rb new file mode 100644 index 00000000000..5f8b1026d3c --- /dev/null +++ b/spec/factories/hierarchy_item_factory.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :hierarchy_item, class: "CustomField::Hierarchy::Item" do + sequence(:label) { |n| "Item #{n}" } + end +end diff --git a/spec/services/custom_fields/hierarchy/hierarchical_item_service_spec.rb b/spec/services/custom_fields/hierarchy/hierarchical_item_service_spec.rb new file mode 100644 index 00000000000..55037c0325c --- /dev/null +++ b/spec/services/custom_fields/hierarchy/hierarchical_item_service_spec.rb @@ -0,0 +1,98 @@ +# 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 "rails_helper" + +RSpec.describe CustomFields::Hierarchy::HierarchicalItemService do + let(:custom_field) { create(:custom_field, field_format: "hierarchy", hierarchy_root: nil) } + let(:invalid_custom_field) { create(:custom_field, field_format: "text", hierarchy_root: nil) } + + describe "#initialize" do + context "with valid custom field" do + it "initializes successfully" do + expect { described_class.new(custom_field) }.not_to raise_error + end + end + + context "with invalid custom field" do + it "raises an ArgumentError" do + expect { described_class.new(invalid_custom_field) }.to raise_error(ArgumentError, /Invalid custom field/) + end + end + end + + describe "#generate_root" do + let(:service) { described_class.new(custom_field) } + + context "with valid hierarchy root" do + it "creates a root item successfully" do + expect(service.generate_root).to be_success + end + end + + context "with invalid hierarchy root" do + it "fails to create a root item" do + allow(CustomField::Hierarchy::Item) + .to receive(:create) + .and_return(instance_double(CustomField::Hierarchy::Item, persisted?: false, errors: "some errors")) + + result = service.generate_root + expect(result).to be_failure + end + end + end + + describe "#insert_item" do + let(:custom_field) { create(:custom_field, field_format: "hierarchy", hierarchy_root: parent) } + let(:service) { described_class.new(custom_field) } + + let(:parent) { create(:hierarchy_item) } + let(:label) { "Child Item" } + let(:short) { "Short Description" } + + context "with valid parameters" do + it "inserts an item successfully" do + result = service.insert_item(parent:, label:, short:) + expect(result).to be_success + end + end + + context "with invalid parameters" do + it "fails to insert an item" do + allow(CustomField::Hierarchy::Item) + .to receive(:create).and_return(instance_double(CustomField::Hierarchy::Item, + persisted?: false, errors: "some errors")) + + result = service.insert_item(parent:, label:, short:) + expect(result).to be_failure + end + end + end +end From c20dc554ad2a2e952d477581daee1a7ef4a981c1 Mon Sep 17 00:00:00 2001 From: Andreas Pfohl Date: Tue, 8 Oct 2024 10:57:49 +0200 Subject: [PATCH 3/4] [58105] Fixed suggestions from PR --- .../hierarchy/service_initialization_contract.rb | 2 +- .../hierarchy/hierarchical_item_service.rb | 2 +- .../hierarchy/hierarchical_item_service_spec.rb | 11 +++++++++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/app/contracts/custom_fields/hierarchy/service_initialization_contract.rb b/app/contracts/custom_fields/hierarchy/service_initialization_contract.rb index 95995bc8d6d..8b72a534ba2 100644 --- a/app/contracts/custom_fields/hierarchy/service_initialization_contract.rb +++ b/app/contracts/custom_fields/hierarchy/service_initialization_contract.rb @@ -36,7 +36,7 @@ module CustomFields end rule(:field_format) do - key.failure("Custom field must have field format 'hierarchy'") unless value == "hierarchy" + key.failure("Custom field must have field format 'hierarchy'") if value != "hierarchy" end end end diff --git a/app/services/custom_fields/hierarchy/hierarchical_item_service.rb b/app/services/custom_fields/hierarchy/hierarchical_item_service.rb index 8ec7940fc0b..d64ae9e7927 100644 --- a/app/services/custom_fields/hierarchy/hierarchical_item_service.rb +++ b/app/services/custom_fields/hierarchy/hierarchical_item_service.rb @@ -53,7 +53,7 @@ module CustomFields def insert_item(parent:, label:, short: nil) CustomFields::Hierarchy::InsertItemContract .new - .call(parent:, label:, short:) + .call({ parent:, label:, short: }.compact) .to_monad .bind { |validation| create_child_item(validation) } end diff --git a/spec/services/custom_fields/hierarchy/hierarchical_item_service_spec.rb b/spec/services/custom_fields/hierarchy/hierarchical_item_service_spec.rb index 55037c0325c..e3b7fd68175 100644 --- a/spec/services/custom_fields/hierarchy/hierarchical_item_service_spec.rb +++ b/spec/services/custom_fields/hierarchy/hierarchical_item_service_spec.rb @@ -57,7 +57,7 @@ RSpec.describe CustomFields::Hierarchy::HierarchicalItemService do end end - context "with invalid hierarchy root" do + context "with persistence of hierarchy root fails" do it "fails to create a root item" do allow(CustomField::Hierarchy::Item) .to receive(:create) @@ -79,12 +79,19 @@ RSpec.describe CustomFields::Hierarchy::HierarchicalItemService do context "with valid parameters" do it "inserts an item successfully" do + result = service.insert_item(parent:, label:) + expect(result).to be_success + end + end + + context "with invalid short" do + it "fails to insert an item" do result = service.insert_item(parent:, label:, short:) expect(result).to be_success end end - context "with invalid parameters" do + context "with invalid item" do it "fails to insert an item" do allow(CustomField::Hierarchy::Item) .to receive(:create).and_return(instance_double(CustomField::Hierarchy::Item, From 06599b2ce944068814e8e1605c81f682b7f2a3d2 Mon Sep 17 00:00:00 2001 From: Andreas Pfohl Date: Tue, 8 Oct 2024 13:51:17 +0200 Subject: [PATCH 4/4] [58105] Renamed context inside hierarchical_item_service_spec --- .../hierarchy/hierarchical_item_service_spec.rb | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/spec/services/custom_fields/hierarchy/hierarchical_item_service_spec.rb b/spec/services/custom_fields/hierarchy/hierarchical_item_service_spec.rb index e3b7fd68175..b5199522c2c 100644 --- a/spec/services/custom_fields/hierarchy/hierarchical_item_service_spec.rb +++ b/spec/services/custom_fields/hierarchy/hierarchical_item_service_spec.rb @@ -78,14 +78,12 @@ RSpec.describe CustomFields::Hierarchy::HierarchicalItemService do let(:short) { "Short Description" } context "with valid parameters" do - it "inserts an item successfully" do + it "inserts an item successfully without short" do result = service.insert_item(parent:, label:) expect(result).to be_success end - end - context "with invalid short" do - it "fails to insert an item" do + it "inserts an item successfully with short" do result = service.insert_item(parent:, label:, short:) expect(result).to be_success end