diff --git a/app/models/award_emoji.rb b/app/models/award_emoji.rb index 1eed0b6becea99aee09577e43d6fdcc0514f304b..d8faea9f885d58ea0536ac5f7196bd6bb6e0a125 100644 --- a/app/models/award_emoji.rb +++ b/app/models/award_emoji.rb @@ -9,6 +9,7 @@ class AwardEmoji < ApplicationRecord include Participable include GhostUser include Importable + include EachBatch belongs_to :awardable, polymorphic: true # rubocop:disable Cop/PolymorphicAssociations belongs_to :user diff --git a/app/services/work_items/data_sync/widgets/award_emoji.rb b/app/services/work_items/data_sync/widgets/award_emoji.rb index c84d6af0649b874a63a3f3b06b885aff45118ada..8021c97d3b19d9bee755b38545d89402fcd2d3e1 100644 --- a/app/services/work_items/data_sync/widgets/award_emoji.rb +++ b/app/services/work_items/data_sync/widgets/award_emoji.rb @@ -4,13 +4,32 @@ module WorkItems module DataSync module Widgets class AwardEmoji < Base - def after_save_commit - # copy emoji, e.g. - # AwardEmojis::CopyService.new(work_item, target_work_item).execute + def after_create + return unless params[:operation] == :move + return unless target_work_item.get_widget(:award_emoji) + + work_item.award_emoji.each_batch(of: BATCH_SIZE) do |awards_batch| + ::AwardEmoji.insert_all(new_work_item_award_emoji(awards_batch)) + end end def post_move_cleanup - # do it + work_item.award_emoji.each_batch(of: BATCH_SIZE) do |award_emoji_batch| + award_emoji_batch.delete_all + end + end + + private + + def new_work_item_award_emoji(awards_batch) + awards_batch.map do |award| + new_award = award.attributes + + new_award.delete("id") + new_award['awardable_id'] = target_work_item.id + + new_award + end end end end diff --git a/spec/services/work_items/data_sync/widgets/award_emoji_spec.rb b/spec/services/work_items/data_sync/widgets/award_emoji_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..077f65914eb287d87d88d53b3d812ebafe2ef7d6 --- /dev/null +++ b/spec/services/work_items/data_sync/widgets/award_emoji_spec.rb @@ -0,0 +1,101 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe WorkItems::DataSync::Widgets::AwardEmoji, feature_category: :team_planning do + let_it_be(:current_user) { create(:user) } + let_it_be_with_reload(:work_item) { create(:work_item) } + let_it_be_with_reload(:thumbs_up) { create(:award_emoji, name: 'thumbsup', awardable: work_item) } + let_it_be_with_reload(:thumbs_down) { create(:award_emoji, name: 'thumbsdown', awardable: work_item) } + + let_it_be(:target_work_item) { create(:work_item) } + let(:params) { { operation: :move } } + + subject(:callback) do + described_class.new( + work_item: work_item, target_work_item: target_work_item, current_user: current_user, params: params + ) + end + + describe '#before_create' do + context 'when target work item has award_emoji widget' do + before do + allow(target_work_item).to receive(:get_widget).with(:award_emoji).and_return(true) + end + + context 'when moving work item' do + it 'copies award_emoji from work_item to target_work_item' do + expect(callback).to receive(:new_work_item_award_emoji).and_call_original + expect(::AwardEmoji).to receive(:insert_all).and_call_original + + expected_result = work_item.reload.award_emoji.order(user_id: :asc, name: :asc).pluck(:user_id, :name) + callback.after_create + + emojis = target_work_item.reload.award_emoji.order(user_id: :asc, name: :asc).pluck(:user_id, :name) + expect(emojis).to match_array(expected_result) + end + end + + context 'when cloning work item' do + let(:params) { { operation: :clone } } + + it 'copies award_emoji from work_item to target_work_item' do + expect(callback).not_to receive(:new_work_item_award_emoji) + expect(::AwardEmoji).not_to receive(:insert_all) + + callback.after_create + + expect(target_work_item.reload.award_emoji).to be_empty + end + end + end + + context 'when target work item does not have award_emoji widget' do + before do + target_work_item.reload + allow(target_work_item).to receive(:get_widget).with(:award_emoji).and_return(false) + end + + it 'does not copy award_emoji' do + expect(callback).not_to receive(:new_work_item_award_emoji) + expect(::AwardEmoji).not_to receive(:insert_all) + + callback.after_create + + expect(target_work_item.reload.award_emoji).to be_empty + end + end + end + + describe '#post_move_cleanup' do + it 'is defined and can be called' do + expect(work_item.award_emoji.count).to eq(2) + expect { callback.post_move_cleanup }.not_to raise_error + end + + it 'removes original work item award_emoji' do + expect(work_item.award_emoji.count).to eq(2) + + callback.post_move_cleanup + + expect(work_item.award_emoji).to be_empty + end + + context 'when cleanup data in batches' do + before do + stub_const("#{described_class}::BATCH_SIZE", 2) + end + + it 'removes original work item award_emoji' do + create(:award_emoji, name: 'star', awardable: work_item) + create(:award_emoji, name: 'grinning', awardable: work_item) + + expect(work_item.award_emoji.count).to eq(4) + + callback.post_move_cleanup + + expect(work_item.reload.award_emoji).to be_empty + end + end + end +end diff --git a/spec/support/shared_examples/services/work_items/data_sync/cloneable_and_moveable_data_stared_examples.rb b/spec/support/shared_examples/services/work_items/data_sync/cloneable_and_moveable_data_stared_examples.rb index d8e5d58031b9a0b193984d4324d723a0eb80074e..70cb8c7e0cc6c1679fa0495ae600a2ffce875376 100644 --- a/spec/support/shared_examples/services/work_items/data_sync/cloneable_and_moveable_data_stared_examples.rb +++ b/spec/support/shared_examples/services/work_items/data_sync/cloneable_and_moveable_data_stared_examples.rb @@ -58,14 +58,25 @@ def work_item_assignees(work_item) work_item.reload.assignees end + def work_item_award_emoji(work_item) + work_item.reload.award_emoji.order(user_id: :asc, name: :asc).pluck(:user_id, :name) + end + where(:widget_name, :eval_value, :before_lambda, :expected_data, :operations) do - :assignees | :work_item_assignees | -> { set_assignees } | ref(:assignees) | [ref(:move), ref(:clone)] + :assignees | :work_item_assignees | -> { set_assignees } | ref(:assignees) | [ref(:move), ref(:clone)] + :award_emoji | :work_item_award_emoji | -> {} | ref(:award_emojis) | [ref(:move)] end with_them do context "with widget" do let(:move) { WorkItems::DataSync::MoveService } let(:clone) { WorkItems::DataSync::CloneService } + let!(:thumbs_ups) { create_list(:award_emoji, 2, name: 'thumbsup', awardable: original_work_item) } + let!(:thumbs_downs) { create_list(:award_emoji, 2, name: 'thumbsdown', awardable: original_work_item) } + + let!(:award_emojis) do + original_work_item.reload.award_emoji.order(user_id: :asc, name: :asc).pluck(:user_id, :name) + end before do instance_exec(&before_lambda)