Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/services/work_items')
-rw-r--r--spec/services/work_items/create_and_link_service_spec.rb40
-rw-r--r--spec/services/work_items/create_from_task_service_spec.rb2
-rw-r--r--spec/services/work_items/create_service_spec.rb10
-rw-r--r--spec/services/work_items/parent_links/create_service_spec.rb28
-rw-r--r--spec/services/work_items/parent_links/destroy_service_spec.rb11
-rw-r--r--spec/services/work_items/update_service_spec.rb119
-rw-r--r--spec/services/work_items/widgets/assignees_service/update_service_spec.rb116
-rw-r--r--spec/services/work_items/widgets/description_service/update_service_spec.rb94
-rw-r--r--spec/services/work_items/widgets/hierarchy_service/update_service_spec.rb26
-rw-r--r--spec/services/work_items/widgets/start_and_due_date_service/update_service_spec.rb62
-rw-r--r--spec/services/work_items/widgets/weight_service/update_service_spec.rb36
11 files changed, 464 insertions, 80 deletions
diff --git a/spec/services/work_items/create_and_link_service_spec.rb b/spec/services/work_items/create_and_link_service_spec.rb
index 81be15f9e2f..e259a22d388 100644
--- a/spec/services/work_items/create_and_link_service_spec.rb
+++ b/spec/services/work_items/create_and_link_service_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe WorkItems::CreateAndLinkService do
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, group: group) }
let_it_be(:user) { create(:user) }
- let_it_be(:related_work_item) { create(:work_item, project: project) }
+ let_it_be(:related_work_item, refind: true) { create(:work_item, project: project) }
let_it_be(:invalid_parent) { create(:work_item, :task, project: project) }
let(:spam_params) { double }
@@ -24,6 +24,26 @@ RSpec.describe WorkItems::CreateAndLinkService do
project.add_developer(user)
end
+ shared_examples 'successful work item and link creator' do
+ it 'creates a work item successfully with links' do
+ expect do
+ service_result
+ end.to change(WorkItem, :count).by(1).and(
+ change(WorkItems::ParentLink, :count).by(1)
+ )
+ end
+
+ it 'copies confidential status from the parent' do
+ expect do
+ service_result
+ end.to change(WorkItem, :count).by(1)
+
+ created_task = WorkItem.last
+
+ expect(created_task.confidential).to eq(related_work_item.confidential)
+ end
+ end
+
describe '#execute' do
subject(:service_result) { described_class.new(project: project, current_user: user, params: params, spam_params: spam_params, link_params: link_params).execute }
@@ -42,15 +62,21 @@ RSpec.describe WorkItems::CreateAndLinkService do
)
end
+ it_behaves_like 'title with extra spaces'
+
context 'when link params are valid' do
let(:link_params) { { parent_work_item: related_work_item } }
- it 'creates a work item successfully with links' do
- expect do
- service_result
- end.to change(WorkItem, :count).by(1).and(
- change(WorkItems::ParentLink, :count).by(1)
- )
+ context 'when parent is not confidential' do
+ it_behaves_like 'successful work item and link creator'
+ end
+
+ context 'when parent is confidential' do
+ before do
+ related_work_item.update!(confidential: true)
+ end
+
+ it_behaves_like 'successful work item and link creator'
end
end
diff --git a/spec/services/work_items/create_from_task_service_spec.rb b/spec/services/work_items/create_from_task_service_spec.rb
index 7d2dab228b1..7c5430f038c 100644
--- a/spec/services/work_items/create_from_task_service_spec.rb
+++ b/spec/services/work_items/create_from_task_service_spec.rb
@@ -64,6 +64,8 @@ RSpec.describe WorkItems::CreateFromTaskService do
expect(list_work_item.description).to eq("- [ ] #{created_work_item.to_reference}+")
end
+
+ it_behaves_like 'title with extra spaces'
end
context 'when last operation fails' do
diff --git a/spec/services/work_items/create_service_spec.rb b/spec/services/work_items/create_service_spec.rb
index 4009c85bacd..c0bcf9b606d 100644
--- a/spec/services/work_items/create_service_spec.rb
+++ b/spec/services/work_items/create_service_spec.rb
@@ -65,6 +65,12 @@ RSpec.describe WorkItems::CreateService do
expect(work_item.description).to eq('please fix')
expect(work_item.work_item_type.base_type).to eq('issue')
end
+
+ it 'calls NewIssueWorker with correct arguments' do
+ expect(NewIssueWorker).to receive(:perform_async).with(Integer, current_user.id, 'WorkItem')
+
+ service_result
+ end
end
context 'when params are invalid' do
@@ -170,7 +176,7 @@ RSpec.describe WorkItems::CreateService do
let_it_be(:parent) { create(:work_item, :task, project: project) }
it_behaves_like 'fails creating work item and returns errors' do
- let(:error_message) { 'only Issue and Incident can be parent of Task.'}
+ let(:error_message) { 'only Issue and Incident can be parent of Task.' }
end
end
@@ -197,7 +203,7 @@ RSpec.describe WorkItems::CreateService do
end
it_behaves_like 'fails creating work item and returns errors' do
- let(:error_message) { 'No matching task found. Make sure that you are adding a valid task ID.'}
+ let(:error_message) { 'No matching task found. Make sure that you are adding a valid task ID.' }
end
end
end
diff --git a/spec/services/work_items/parent_links/create_service_spec.rb b/spec/services/work_items/parent_links/create_service_spec.rb
index 85b0ee040cd..0ba41373544 100644
--- a/spec/services/work_items/parent_links/create_service_spec.rb
+++ b/spec/services/work_items/parent_links/create_service_spec.rb
@@ -12,10 +12,10 @@ RSpec.describe WorkItems::ParentLinks::CreateService do
let_it_be(:task1) { create(:work_item, :task, project: project) }
let_it_be(:task2) { create(:work_item, :task, project: project) }
let_it_be(:guest_task) { create(:work_item, :task) }
- let_it_be(:invalid_task) { build_stubbed(:work_item, :task, id: non_existing_record_id)}
+ let_it_be(:invalid_task) { build_stubbed(:work_item, :task, id: non_existing_record_id) }
let_it_be(:another_project) { (create :project) }
let_it_be(:other_project_task) { create(:work_item, :task, iid: 100, project: another_project) }
- let_it_be(:existing_parent_link) { create(:parent_link, work_item: task, work_item_parent: work_item)}
+ let_it_be(:existing_parent_link) { create(:parent_link, work_item: task, work_item_parent: work_item) }
let(:parent_link_class) { WorkItems::ParentLink }
let(:issuable_type) { :task }
@@ -84,13 +84,26 @@ RSpec.describe WorkItems::ParentLinks::CreateService do
expect(subject[:created_references].map(&:work_item_id)).to match_array([task1.id, task2.id])
end
+ it 'creates notes', :aggregate_failures do
+ subject
+
+ work_item_notes = work_item.notes.last(2)
+ expect(work_item_notes.first.note).to eq("added #{task1.to_reference} as child task")
+ expect(work_item_notes.last.note).to eq("added #{task2.to_reference} as child task")
+ expect(task1.notes.last.note).to eq("added #{work_item.to_reference} as parent issue")
+ expect(task2.notes.last.note).to eq("added #{work_item.to_reference} as parent issue")
+ end
+
context 'when task is already assigned' do
let(:params) { { issuable_references: [task, task2] } }
- it 'creates links only for non related tasks' do
+ it 'creates links only for non related tasks', :aggregate_failures do
expect { subject }.to change(parent_link_class, :count).by(1)
expect(subject[:created_references].map(&:work_item_id)).to match_array([task2.id])
+ expect(work_item.notes.last.note).to eq("added #{task2.to_reference} as child task")
+ expect(task2.notes.last.note).to eq("added #{work_item.to_reference} as parent issue")
+ expect(task.notes).to be_empty
end
end
@@ -109,6 +122,15 @@ RSpec.describe WorkItems::ParentLinks::CreateService do
is_expected.to eq(service_error(error, http_status: 422))
end
+
+ it 'creates notes for valid links' do
+ subject
+
+ expect(work_item.notes.last.note).to eq("added #{task1.to_reference} as child task")
+ expect(task1.notes.last.note).to eq("added #{work_item.to_reference} as parent issue")
+ expect(issue.notes).to be_empty
+ expect(other_project_task.notes).to be_empty
+ end
end
context 'when parent type is invalid' do
diff --git a/spec/services/work_items/parent_links/destroy_service_spec.rb b/spec/services/work_items/parent_links/destroy_service_spec.rb
index 574b70af397..654a03ef6f7 100644
--- a/spec/services/work_items/parent_links/destroy_service_spec.rb
+++ b/spec/services/work_items/parent_links/destroy_service_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe WorkItems::ParentLinks::DestroyService do
let_it_be(:project) { create(:project) }
let_it_be(:work_item) { create(:work_item, project: project) }
let_it_be(:task) { create(:work_item, :task, project: project) }
- let_it_be(:parent_link) { create(:parent_link, work_item: task, work_item_parent: work_item)}
+ let_it_be(:parent_link) { create(:parent_link, work_item: task, work_item_parent: work_item) }
let(:parent_link_class) { WorkItems::ParentLink }
@@ -23,8 +23,11 @@ RSpec.describe WorkItems::ParentLinks::DestroyService do
context 'when user has permissions to update work items' do
let(:user) { reporter }
- it 'removes relation' do
+ it 'removes relation and creates notes', :aggregate_failures do
expect { subject }.to change(parent_link_class, :count).by(-1)
+
+ expect(work_item.notes.last.note).to eq("removed child task #{task.to_reference}")
+ expect(task.notes.last.note).to eq("removed parent issue #{work_item.to_reference}")
end
it 'returns success message' do
@@ -35,8 +38,10 @@ RSpec.describe WorkItems::ParentLinks::DestroyService do
context 'when user has insufficient permissions' do
let(:user) { guest }
- it 'does not remove relation' do
+ it 'does not remove relation', :aggregate_failures do
expect { subject }.not_to change(parent_link_class, :count).from(1)
+
+ expect(SystemNoteService).not_to receive(:unrelate_work_item)
end
it 'returns error message' do
diff --git a/spec/services/work_items/update_service_spec.rb b/spec/services/work_items/update_service_spec.rb
index b17c9ffb4fb..2e0b0051495 100644
--- a/spec/services/work_items/update_service_spec.rb
+++ b/spec/services/work_items/update_service_spec.rb
@@ -4,7 +4,8 @@ require 'spec_helper'
RSpec.describe WorkItems::UpdateService do
let_it_be(:developer) { create(:user) }
- let_it_be(:project) { create(:project).tap { |proj| proj.add_developer(developer) } }
+ let_it_be(:guest) { create(:user) }
+ let_it_be(:project) { create(:project) }
let_it_be(:parent) { create(:work_item, project: project) }
let_it_be_with_reload(:work_item) { create(:work_item, project: project, assignees: [developer]) }
@@ -13,21 +14,36 @@ RSpec.describe WorkItems::UpdateService do
let(:opts) { {} }
let(:current_user) { developer }
+ before do
+ project.add_developer(developer)
+ project.add_guest(guest)
+ end
+
describe '#execute' do
- subject(:update_work_item) do
+ let(:service) do
described_class.new(
project: project,
current_user: current_user,
params: opts,
spam_params: spam_params,
widget_params: widget_params
- ).execute(work_item)
+ )
end
+ subject(:update_work_item) { service.execute(work_item) }
+
before do
stub_spam_services
end
+ shared_examples 'update service that triggers graphql dates updated subscription' do
+ it 'triggers graphql subscription issueableDatesUpdated' do
+ expect(GraphqlTriggers).to receive(:issuable_dates_updated).with(work_item).and_call_original
+
+ update_work_item
+ end
+ end
+
context 'when title is changed' do
let(:opts) { { title: 'changed' } }
@@ -50,6 +66,16 @@ RSpec.describe WorkItems::UpdateService do
end
end
+ context 'when dates are changed' do
+ let(:opts) { { start_date: Date.today } }
+
+ it 'tracks users updating work item dates' do
+ expect(Gitlab::UsageDataCounters::WorkItemActivityUniqueCounter).to receive(:track_work_item_date_changed_action).with(author: current_user)
+
+ update_work_item
+ end
+ end
+
context 'when updating state_event' do
context 'when state_event is close' do
let(:opts) { { state_event: 'close' } }
@@ -82,8 +108,7 @@ RSpec.describe WorkItems::UpdateService do
let(:widget_params) do
{
hierarchy_widget: { parent: parent },
- description_widget: { description: 'foo' },
- weight_widget: { weight: 1 }
+ description_widget: { description: 'foo' }
}
end
@@ -101,8 +126,7 @@ RSpec.describe WorkItems::UpdateService do
let(:supported_widgets) do
[
- { klass: WorkItems::Widgets::DescriptionService::UpdateService, callback: :update, params: { description: 'foo' } },
- { klass: WorkItems::Widgets::WeightService::UpdateService, callback: :update, params: { weight: 1 } },
+ { klass: WorkItems::Widgets::DescriptionService::UpdateService, callback: :before_update_callback, params: { description: 'foo' } },
{ klass: WorkItems::Widgets::HierarchyService::UpdateService, callback: :before_update_in_transaction, params: { parent: parent } }
]
end
@@ -126,7 +150,7 @@ RSpec.describe WorkItems::UpdateService do
before do
allow_next_instance_of(widget_service_class) do |instance|
allow(instance)
- .to receive(:update)
+ .to receive(:before_update_callback)
.with(params: { description: 'changed' }).and_return(nil)
end
end
@@ -142,6 +166,69 @@ RSpec.describe WorkItems::UpdateService do
expect(work_item.description).to eq('changed')
end
+
+ context 'with mentions', :mailer, :sidekiq_might_not_need_inline do
+ shared_examples 'creates the todo and sends email' do |attribute|
+ it 'creates a todo and sends email' do
+ expect { perform_enqueued_jobs { update_work_item } }.to change(Todo, :count).by(1)
+ expect(work_item.reload.attributes[attribute.to_s]).to eq("mention #{guest.to_reference}")
+ should_email(guest)
+ end
+ end
+
+ context 'when description contains a user mention' do
+ let(:widget_params) { { description_widget: { description: "mention #{guest.to_reference}" } } }
+
+ it_behaves_like 'creates the todo and sends email', :description
+ end
+
+ context 'when title contains a user mention' do
+ let(:opts) { { title: "mention #{guest.to_reference}" } }
+
+ it_behaves_like 'creates the todo and sends email', :title
+ end
+ end
+
+ context 'when work item validation fails' do
+ let(:opts) { { title: '' } }
+
+ it 'returns validation errors' do
+ expect(update_work_item[:message]).to contain_exactly("Title can't be blank")
+ end
+
+ it 'does not execute after-update widgets', :aggregate_failures do
+ expect(service).to receive(:update).and_call_original
+ expect(service).not_to receive(:execute_widgets).with(callback: :update, widget_params: widget_params)
+
+ expect { update_work_item }.not_to change(work_item, :description)
+ end
+ end
+ end
+
+ context 'for start and due date widget' do
+ let(:updated_date) { 1.week.from_now.to_date }
+
+ context 'when due_date is updated' do
+ let(:widget_params) { { start_and_due_date_widget: { due_date: updated_date } } }
+
+ it_behaves_like 'update service that triggers graphql dates updated subscription'
+ end
+
+ context 'when start_date is updated' do
+ let(:widget_params) { { start_and_due_date_widget: { start_date: updated_date } } }
+
+ it_behaves_like 'update service that triggers graphql dates updated subscription'
+ end
+
+ context 'when no date param is updated' do
+ let(:opts) { { title: 'should not trigger' } }
+
+ it 'does not trigger date updated subscription' do
+ expect(GraphqlTriggers).not_to receive(:issuable_dates_updated)
+
+ update_work_item
+ end
+ end
end
context 'for the hierarchy widget' do
@@ -175,6 +262,22 @@ RSpec.describe WorkItems::UpdateService do
end.to not_change(WorkItems::ParentLink, :count).and(not_change(work_item, :title))
end
end
+
+ context 'when work item validation fails' do
+ let(:opts) { { title: '' } }
+
+ it 'returns validation errors' do
+ expect(update_work_item[:message]).to contain_exactly("Title can't be blank")
+ end
+
+ it 'does not execute after-update widgets', :aggregate_failures do
+ expect(service).to receive(:update).and_call_original
+ expect(service).not_to receive(:execute_widgets).with(callback: :before_update_in_transaction, widget_params: widget_params)
+ expect(work_item.work_item_children).not_to include(child_work_item)
+
+ update_work_item
+ end
+ end
end
end
end
diff --git a/spec/services/work_items/widgets/assignees_service/update_service_spec.rb b/spec/services/work_items/widgets/assignees_service/update_service_spec.rb
new file mode 100644
index 00000000000..0ab2c85f078
--- /dev/null
+++ b/spec/services/work_items/widgets/assignees_service/update_service_spec.rb
@@ -0,0 +1,116 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe WorkItems::Widgets::AssigneesService::UpdateService, :freeze_time do
+ let_it_be(:reporter) { create(:user) }
+ let_it_be(:project) { create(:project, :private) }
+ let_it_be(:new_assignee) { create(:user) }
+
+ let(:work_item) do
+ create(:work_item, project: project, updated_at: 1.day.ago)
+ end
+
+ let(:widget) { work_item.widgets.find { |widget| widget.is_a?(WorkItems::Widgets::Assignees) } }
+ let(:current_user) { reporter }
+ let(:params) { { assignee_ids: [new_assignee.id] } }
+
+ before_all do
+ project.add_reporter(reporter)
+ project.add_guest(new_assignee)
+ end
+
+ describe '#before_update_in_transaction' do
+ subject do
+ described_class.new(widget: widget, current_user: current_user)
+ .before_update_in_transaction(params: params)
+ end
+
+ it 'updates the assignees and sets updated_at to the current time' do
+ subject
+
+ expect(work_item.assignee_ids).to contain_exactly(new_assignee.id)
+ expect(work_item.updated_at).to be_like_time(Time.current)
+ end
+
+ context 'when passing an empty array' do
+ let(:params) { { assignee_ids: [] } }
+
+ before do
+ work_item.assignee_ids = [reporter.id]
+ end
+
+ it 'removes existing assignees' do
+ subject
+
+ expect(work_item.assignee_ids).to be_empty
+ expect(work_item.updated_at).to be_like_time(Time.current)
+ end
+ end
+
+ context 'when user does not have access' do
+ let(:current_user) { create(:user) }
+
+ it 'does not update the assignees' do
+ subject
+
+ expect(work_item.assignee_ids).to be_empty
+ expect(work_item.updated_at).to be_like_time(1.day.ago)
+ end
+ end
+
+ context 'when multiple assignees are given' do
+ let(:params) { { assignee_ids: [new_assignee.id, reporter.id] } }
+
+ context 'when work item allows multiple assignees' do
+ before do
+ allow(work_item).to receive(:allows_multiple_assignees?).and_return(true)
+ end
+
+ it 'sets all the given assignees' do
+ subject
+
+ expect(work_item.assignee_ids).to contain_exactly(new_assignee.id, reporter.id)
+ expect(work_item.updated_at).to be_like_time(Time.current)
+ end
+ end
+
+ context 'when work item does not allow multiple assignees' do
+ before do
+ allow(work_item).to receive(:allows_multiple_assignees?).and_return(false)
+ end
+
+ it 'only sets the first assignee' do
+ subject
+
+ expect(work_item.assignee_ids).to contain_exactly(new_assignee.id)
+ expect(work_item.updated_at).to be_like_time(Time.current)
+ end
+ end
+ end
+
+ context 'when assignee does not have access to the work item' do
+ let(:params) { { assignee_ids: [create(:user).id] } }
+
+ it 'does not set the assignee' do
+ subject
+
+ expect(work_item.assignee_ids).to be_empty
+ expect(work_item.updated_at).to be_like_time(1.day.ago)
+ end
+ end
+
+ context 'when assignee ids are the same as the existing ones' do
+ before do
+ work_item.assignee_ids = [new_assignee.id]
+ end
+
+ it 'does not touch updated_at' do
+ subject
+
+ expect(work_item.assignee_ids).to contain_exactly(new_assignee.id)
+ expect(work_item.updated_at).to be_like_time(1.day.ago)
+ end
+ end
+ end
+end
diff --git a/spec/services/work_items/widgets/description_service/update_service_spec.rb b/spec/services/work_items/widgets/description_service/update_service_spec.rb
index a2eceb97f09..582d9dc85f7 100644
--- a/spec/services/work_items/widgets/description_service/update_service_spec.rb
+++ b/spec/services/work_items/widgets/description_service/update_service_spec.rb
@@ -3,32 +3,102 @@
require 'spec_helper'
RSpec.describe WorkItems::Widgets::DescriptionService::UpdateService do
- let_it_be(:user) { create(:user) }
- let_it_be(:project) { create(:project) }
- let_it_be_with_reload(:work_item) { create(:work_item, project: project, description: 'old description') }
+ let_it_be(:random_user) { create(:user) }
+ let_it_be(:author) { create(:user) }
+ let_it_be(:guest) { create(:user) }
+ let_it_be(:reporter) { create(:user) }
+ let_it_be(:project) { create(:project, :public) }
- let(:widget) { work_item.widgets.find {|widget| widget.is_a?(WorkItems::Widgets::Description) } }
+ let(:params) { { description: 'updated description' } }
+ let(:current_user) { author }
+ let(:work_item) do
+ create(:work_item, author: author, project: project, description: 'old description',
+ last_edited_at: Date.yesterday, last_edited_by: random_user
+ )
+ end
- describe '#update' do
- subject { described_class.new(widget: widget, current_user: user).update(params: params) } # rubocop:disable Rails/SaveBang
+ let(:widget) { work_item.widgets.find { |widget| widget.is_a?(WorkItems::Widgets::Description) } }
- context 'when description param is present' do
- let(:params) { { description: 'updated description' } }
+ describe '#update' do
+ subject { described_class.new(widget: widget, current_user: current_user).before_update_callback(params: params) }
+ shared_examples 'sets work item description' do
it 'correctly sets work item description value' do
subject
- expect(work_item.description).to eq('updated description')
+ expect(work_item.description).to eq(params[:description])
+ expect(work_item.last_edited_by).to eq(current_user)
+ expect(work_item.last_edited_at).to be_within(2.seconds).of(Time.current)
end
end
- context 'when description param is not present' do
- let(:params) { {} }
-
+ shared_examples 'does not set work item description' do
it 'does not change work item description value' do
subject
expect(work_item.description).to eq('old description')
+ expect(work_item.last_edited_by).to eq(random_user)
+ expect(work_item.last_edited_at).to eq(Date.yesterday)
+ end
+ end
+
+ context 'when user has permission to update description' do
+ context 'when user is work item author' do
+ let(:current_user) { author }
+
+ it_behaves_like 'sets work item description'
+ end
+
+ context 'when user is a project reporter' do
+ let(:current_user) { reporter }
+
+ before do
+ project.add_reporter(reporter)
+ end
+
+ it_behaves_like 'sets work item description'
+ end
+
+ context 'when description is nil' do
+ let(:current_user) { author }
+ let(:params) { { description: nil } }
+
+ it_behaves_like 'sets work item description'
+ end
+
+ context 'when description is empty' do
+ let(:current_user) { author }
+ let(:params) { { description: '' } }
+
+ it_behaves_like 'sets work item description'
+ end
+
+ context 'when description param is not present' do
+ let(:params) { {} }
+
+ it_behaves_like 'does not set work item description'
+ end
+ end
+
+ context 'when user does not have permission to update description' do
+ context 'when user is a project guest' do
+ let(:current_user) { guest }
+
+ before do
+ project.add_guest(guest)
+ end
+
+ it_behaves_like 'does not set work item description'
+ end
+
+ context 'with private project' do
+ let_it_be(:project) { create(:project) }
+
+ context 'when user is work item author' do
+ let(:current_user) { author }
+
+ it_behaves_like 'does not set work item description'
+ end
end
end
end
diff --git a/spec/services/work_items/widgets/hierarchy_service/update_service_spec.rb b/spec/services/work_items/widgets/hierarchy_service/update_service_spec.rb
index 4f6ff1b8676..9a425d5308c 100644
--- a/spec/services/work_items/widgets/hierarchy_service/update_service_spec.rb
+++ b/spec/services/work_items/widgets/hierarchy_service/update_service_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe WorkItems::Widgets::HierarchyService::UpdateService do
let_it_be(:child_work_item) { create(:work_item, :task, project: project) }
let_it_be(:existing_link) { create(:parent_link, work_item: child_work_item, work_item_parent: work_item) }
- let(:widget) { work_item.widgets.find {|widget| widget.is_a?(WorkItems::Widgets::Hierarchy) } }
+ let(:widget) { work_item.widgets.find { |widget| widget.is_a?(WorkItems::Widgets::Hierarchy) } }
let(:not_found_error) { 'No matching task found. Make sure that you are adding a valid task ID.' }
shared_examples 'raises a WidgetError' do
@@ -29,13 +29,21 @@ RSpec.describe WorkItems::Widgets::HierarchyService::UpdateService do
end
end
+ context 'when invalid params are present' do
+ let(:params) { { other_parent: parent_work_item } }
+
+ it_behaves_like 'raises a WidgetError' do
+ let(:message) { 'One or more arguments are invalid: other_parent.' }
+ end
+ end
+
context 'when updating children' do
let_it_be(:child_work_item2) { create(:work_item, :task, project: project) }
let_it_be(:child_work_item3) { create(:work_item, :task, project: project) }
let_it_be(:child_work_item4) { create(:work_item, :task, project: project) }
context 'when work_items_hierarchy feature flag is disabled' do
- let(:params) { { children: [child_work_item4] }}
+ let(:params) { { children: [child_work_item4] } }
before do
stub_feature_flags(work_items_hierarchy: false)
@@ -47,7 +55,7 @@ RSpec.describe WorkItems::Widgets::HierarchyService::UpdateService do
end
context 'when user has insufficient permissions to link work items' do
- let(:params) { { children: [child_work_item4] }}
+ let(:params) { { children: [child_work_item4] } }
it_behaves_like 'raises a WidgetError' do
let(:message) { not_found_error }
@@ -60,7 +68,7 @@ RSpec.describe WorkItems::Widgets::HierarchyService::UpdateService do
end
context 'with valid params' do
- let(:params) { { children: [child_work_item2, child_work_item3] }}
+ let(:params) { { children: [child_work_item2, child_work_item3] } }
it 'correctly sets work item parent' do
subject
@@ -71,7 +79,7 @@ RSpec.describe WorkItems::Widgets::HierarchyService::UpdateService do
end
context 'when child is already assigned' do
- let(:params) { { children: [child_work_item] }}
+ let(:params) { { children: [child_work_item] } }
it_behaves_like 'raises a WidgetError' do
let(:message) { 'Task(s) already assigned' }
@@ -81,7 +89,7 @@ RSpec.describe WorkItems::Widgets::HierarchyService::UpdateService do
context 'when child type is invalid' do
let_it_be(:child_issue) { create(:work_item, project: project) }
- let(:params) { { children: [child_issue] }}
+ let(:params) { { children: [child_issue] } }
it_behaves_like 'raises a WidgetError' do
let(:message) do
@@ -95,7 +103,7 @@ RSpec.describe WorkItems::Widgets::HierarchyService::UpdateService do
context 'when updating parent' do
let_it_be(:work_item) { create(:work_item, :task, project: project) }
- let(:params) {{ parent: parent_work_item } }
+ let(:params) { { parent: parent_work_item } }
context 'when work_items_hierarchy feature flag is disabled' do
before do
@@ -144,9 +152,9 @@ RSpec.describe WorkItems::Widgets::HierarchyService::UpdateService do
end
context 'when type is invalid' do
- let_it_be(:parent_task) { create(:work_item, :task, project: project)}
+ let_it_be(:parent_task) { create(:work_item, :task, project: project) }
- let(:params) {{ parent: parent_task } }
+ let(:params) { { parent: parent_task } }
it_behaves_like 'raises a WidgetError' do
let(:message) do
diff --git a/spec/services/work_items/widgets/start_and_due_date_service/update_service_spec.rb b/spec/services/work_items/widgets/start_and_due_date_service/update_service_spec.rb
new file mode 100644
index 00000000000..d328c541fc7
--- /dev/null
+++ b/spec/services/work_items/widgets/start_and_due_date_service/update_service_spec.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe WorkItems::Widgets::StartAndDueDateService::UpdateService do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be_with_reload(:work_item) { create(:work_item, project: project) }
+
+ let(:widget) { work_item.widgets.find { |widget| widget.is_a?(WorkItems::Widgets::StartAndDueDate) } }
+
+ describe '#before_update_callback' do
+ let(:start_date) { Date.today }
+ let(:due_date) { 1.week.from_now.to_date }
+
+ subject(:update_params) do
+ described_class.new(widget: widget, current_user: user).before_update_callback(params: params)
+ end
+
+ context 'when start and due date params are present' do
+ let(:params) { { start_date: Date.today, due_date: 1.week.from_now.to_date } }
+
+ it 'correctly sets date values' do
+ expect do
+ update_params
+ end.to change(work_item, :start_date).from(nil).to(start_date).and(
+ change(work_item, :due_date).from(nil).to(due_date)
+ )
+ end
+ end
+
+ context 'when date params are not present' do
+ let(:params) { {} }
+
+ it 'does not change work item date values' do
+ expect do
+ update_params
+ end.to not_change(work_item, :start_date).from(nil).and(
+ not_change(work_item, :due_date).from(nil)
+ )
+ end
+ end
+
+ context 'when work item had both date values already set' do
+ before do
+ work_item.update!(start_date: start_date, due_date: due_date)
+ end
+
+ context 'when one of the two params is null' do
+ let(:params) { { start_date: nil } }
+
+ it 'sets only one date to null' do
+ expect do
+ update_params
+ end.to change(work_item, :start_date).from(start_date).to(nil).and(
+ not_change(work_item, :due_date).from(due_date)
+ )
+ end
+ end
+ end
+ end
+end
diff --git a/spec/services/work_items/widgets/weight_service/update_service_spec.rb b/spec/services/work_items/widgets/weight_service/update_service_spec.rb
deleted file mode 100644
index 97e17f1c526..00000000000
--- a/spec/services/work_items/widgets/weight_service/update_service_spec.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe WorkItems::Widgets::WeightService::UpdateService do
- let_it_be(:user) { create(:user) }
- let_it_be(:project) { create(:project) }
- let_it_be_with_reload(:work_item) { create(:work_item, project: project, weight: 1) }
-
- let(:widget) { work_item.widgets.find {|widget| widget.is_a?(WorkItems::Widgets::Weight) } }
-
- describe '#update' do
- subject { described_class.new(widget: widget, current_user: user).update(params: params) } # rubocop:disable Rails/SaveBang
-
- context 'when weight param is present' do
- let(:params) { { weight: 2 } }
-
- it 'correctly sets work item weight value' do
- subject
-
- expect(work_item.weight).to eq(2)
- end
- end
-
- context 'when weight param is not present' do
- let(:params) { {} }
-
- it 'does not change work item weight value', :aggregate_failures do
- expect { subject }
- .to not_change { work_item.weight }
-
- expect(work_item.weight).to eq(1)
- end
- end
- end
-end