Skip to content
代码片段 群组 项目
未验证 提交 00ab9b93 编辑于 作者: Alexandru Croitor's avatar Alexandru Croitor
浏览文件

Improve move and clone work item specs performance

Instead of running the move or clone service for each widget
we can run it once with all widgets and check that the output
is the expected one for each widget data. This reduces the time
spent on running the spec as we run it once vs 8 times now and
more times as we keep adding widgets.

This also prevents issues where the order in which some widgets
are run is important.
上级 c3695b5c
No related branches found
No related tags found
无相关合并请求
# frozen_string_literal: true
RSpec.shared_examples 'cloneable and moveable for ee widget data' do
def work_item_weights_source(work_item)
work_item.reload.weights_source&.slice(:rolled_up_weight, :rolled_up_completed_weight)
end
let_it_be(:weights_source) do
weights_source = create(:work_item_weights_source, work_item: original_work_item, rolled_up_weight: 20,
rolled_up_completed_weight: 50)
weights_source&.slice(:rolled_up_weight, :rolled_up_completed_weight)
end
let_it_be(:move) { WorkItems::DataSync::MoveService }
let_it_be(:clone) { WorkItems::DataSync::CloneService }
# rubocop: disable Layout/LineLength -- improved readability with one line per widget
let_it_be(:widgets) do
[
{ widget_name: :weights_source, eval_value: :work_item_weights_source, expected_data: weights_source, operations: [move, clone] }
]
end
# rubocop: enable Layout/LineLength
with_them do
context "with widget" do
it_behaves_like 'for clone and move services'
end
end
end
......@@ -62,8 +62,6 @@
end
RSpec.shared_examples 'cloneable and moveable widget data' do
using RSpec::Parameterized::TableSyntax
def work_item_assignees(work_item)
work_item.reload.assignees
end
......@@ -175,79 +173,60 @@ def work_item_crm_contacts(work_item)
timelogs.pluck(:user_id, :time_spent)
end
where(:widget_name, :eval_value, :expected_data, :operations) do
:assignees | :work_item_assignees | ref(:assignees) | [ref(:move), ref(:clone)]
:award_emoji | :work_item_award_emoji | ref(:award_emojis) | [ref(:move)]
:email_participants | :work_item_emails | ref(:emails) | [ref(:move)]
:milestone | :work_item_milestone | ref(:milestone) | [ref(:move), ref(:clone)]
:subscriptions | :work_item_subscriptions | ref(:subscriptions) | [ref(:move)]
:sent_notifications | :work_item_sent_notifications | ref(:notifications) | [ref(:move)]
:timelogs | :work_item_timelogs | ref(:timelogs) | [ref(:move)]
:customer_relations_contacts | :work_item_crm_contacts | ref(:crm_contacts) | [ref(:move), ref(:clone)]
end
with_them do
context "with widget" do
before do
allow(original_work_item).to receive(:from_service_desk?).and_return(true)
allow(WorkItems::CopyTimelogsWorker).to receive(:perform_async) do |*args|
WorkItems::CopyTimelogsWorker.perform_inline(*args)
end
let_it_be(:move) { WorkItems::DataSync::MoveService }
let_it_be(:clone) { WorkItems::DataSync::CloneService }
# rubocop: disable Layout/LineLength -- improved readability with one line per widget
let_it_be(:widgets) do
[
{ widget_name: :assignees, eval_value: :work_item_assignees, expected_data: assignees, operations: [move, clone] },
{ widget_name: :award_emoji, eval_value: :work_item_award_emoji, expected_data: award_emojis, operations: [move] },
{ widget_name: :email_participants, eval_value: :work_item_emails, expected_data: emails, operations: [move] },
{ widget_name: :milestone, eval_value: :work_item_milestone, expected_data: milestone, operations: [move, clone] },
{ widget_name: :subscriptions, eval_value: :work_item_subscriptions, expected_data: subscriptions, operations: [move] },
{ widget_name: :sent_notifications, eval_value: :work_item_sent_notifications, expected_data: notifications, operations: [move] },
{ widget_name: :timelogs, eval_value: :work_item_timelogs, expected_data: timelogs, operations: [move] },
{ widget_name: :customer_relations_contacts, eval_value: :work_item_crm_contacts, expected_data: crm_contacts, operations: [move, clone] }
]
end
# rubocop: enable Layout/LineLength
context "with widget" do
before do
allow(original_work_item).to receive(:from_service_desk?).and_return(true)
allow(WorkItems::CopyTimelogsWorker).to receive(:perform_async) do |*args|
WorkItems::CopyTimelogsWorker.perform_inline(*args)
end
it_behaves_like 'for clone and move services'
end
end
RSpec.shared_examples 'cloneable and moveable for ee widget data' do
using RSpec::Parameterized::TableSyntax
def work_item_weights_source(work_item)
work_item.reload.weights_source&.slice(:rolled_up_weight, :rolled_up_completed_weight)
end
let_it_be(:weights_source) do
weights_source = create(:work_item_weights_source, work_item: original_work_item, rolled_up_weight: 20,
rolled_up_completed_weight: 50)
weights_source&.slice(:rolled_up_weight, :rolled_up_completed_weight)
end
where(:widget_name, :eval_value, :expected_data, :operations) do
:weights_source | :work_item_weights_source | ref(:weights_source) | [ref(:move), ref(:clone)]
end
with_them do
context "with widget" do
it_behaves_like 'for clone and move services'
end
end
it_behaves_like 'for clone and move services'
end
end
# this shared context is only to be used for sharing the code beetween the shared examples for cloneable and movable
# this shared example is only to be used for sharing the code between the shared examples for cloneable and movable
# widget data (and for EE widget data)
RSpec.shared_context 'for clone and move services' do
let(:move) { WorkItems::DataSync::MoveService }
let(:clone) { WorkItems::DataSync::CloneService }
it 'clones and moves the data', :aggregate_failures do
RSpec.shared_examples 'for clone and move services' do
it 'clones and moves the data', :aggregate_failures, :sidekiq_inline do
new_work_item = service.execute[:work_item]
widget_value = send(eval_value, new_work_item)
if operations.include?(described_class)
expect(widget_value).not_to be_blank
# trick to compare single values and arrays with a single statement
expect([widget_value].flatten).to match_array([expected_data].flatten)
else
expect(widget_value).to be_blank
end
widgets.each do |widget|
widget_value = send(widget[:eval_value], new_work_item)
if widget[:operations].include?(described_class)
expect(widget_value).not_to be_blank
# trick to compare single values and arrays with a single statement
expect([widget_value].flatten).to match_array([widget[:expected_data]].flatten)
else
expect(widget_value).to be_blank
end
cleanup_data = Feature.enabled?(:cleanup_data_source_work_item_data, original_work_item.resource_parent)
if cleanup_data && described_class == move
expect(original_work_item.reload.public_send(widget_name)).to be_blank
elsif widget_name != :sent_notifications
# sent notifications are moved from original work item to new work item rather than deleted afterwards.
expect(original_work_item.reload.public_send(widget_name)).not_to be_blank
cleanup_data = Feature.enabled?(:cleanup_data_source_work_item_data, original_work_item.resource_parent)
if cleanup_data && described_class == move
expect(original_work_item.reload.public_send(widget[:widget_name])).to be_blank
elsif widget[:widget_name] != :sent_notifications
# sent notifications are moved from original work item to new work item rather than deleted afterwards.
expect(original_work_item.reload.public_send(widget[:widget_name])).not_to be_blank
end
end
end
end
0% 加载中 .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册