# frozen_string_literal: true RSpec.describe SidebarSiteSettingsBackfiller do fab!(:user) { Fabricate(:user) } fab!(:user2) { Fabricate(:user) } fab!(:user3) { Fabricate(:user) } fab!(:staged_user) { Fabricate(:user, staged: true) } fab!(:category) { Fabricate(:category) } fab!(:category2) { Fabricate(:category) } fab!(:category3) { Fabricate(:category) } fab!(:user_category_sidebar_section_link) { Fabricate(:category_sidebar_section_link, user: user, linkable: category) } fab!(:user2_category_sidebar_section_link) { Fabricate(:category_sidebar_section_link, user: user2, linkable: category) } fab!(:user3_category2_sidebar_section_link) { Fabricate(:category_sidebar_section_link, user: user3, linkable: category2) } let!(:category_sidebar_section_link_ids) do [ user_category_sidebar_section_link.id, user2_category_sidebar_section_link.id, user3_category2_sidebar_section_link.id ] end fab!(:tag) { Fabricate(:tag) } fab!(:tag2) { Fabricate(:tag) } fab!(:tag3) { Fabricate(:tag) } fab!(:user_tag_sidebar_section_link) { Fabricate(:tag_sidebar_section_link, user: user, linkable: tag) } fab!(:user2_tag_sidebar_section_link) { Fabricate(:tag_sidebar_section_link, user: user2, linkable: tag) } fab!(:user3_tag2_sidebar_section_link) { Fabricate(:tag_sidebar_section_link, user: user3, linkable: tag2) } let!(:tag_sidebar_section_link_ids) do [ user_tag_sidebar_section_link.id, user2_tag_sidebar_section_link.id, user3_tag2_sidebar_section_link.id ] end before do # Clean up random users created as part of fabrication to make assertions easier to understand. User.real.where("id NOT IN (?)", [user.id, user2.id, user3.id, staged_user.id]).delete_all end it 'raises an error when class is initialized with invalid setting name' do expect do described_class.new('some_random_setting_name', previous_value: '', new_value: '') end.to raise_error(RuntimeError, "Invalid setting_name") end describe '#backfill!' do context 'for default_sidebar_categories setting' do it 'deletes the right sidebar section link records when categories are removed' do backfiller = described_class.new( "default_sidebar_categories", previous_value: "#{category.id}|#{category2.id}|#{category3.id}", new_value: "#{category3.id}" ) expect do backfiller.backfill! end.to change { SidebarSectionLink.count }.by(-3) expect(SidebarSectionLink.exists?(id: category_sidebar_section_link_ids)).to eq(false) end it 'creates the right sidebar section link records when categories are added' do backfiller = described_class.new( "default_sidebar_categories", previous_value: "#{category.id}|#{category2.id}", new_value: "#{category.id}|#{category2.id}|#{category3.id}" ) expect do backfiller.backfill! end.to change { SidebarSectionLink.count }.by(3) expect(SidebarSectionLink.where(linkable_type: 'Category', linkable_id: category3.id).pluck(:user_id)).to contain_exactly( user.id, user2.id, user3.id ) end it 'creates the right sidebar section link records when categories are added' do backfiller = described_class.new( "default_sidebar_categories", previous_value: "", new_value: "#{category.id}|#{category2.id}|#{category3.id}" ) expect do backfiller.backfill! end.to change { SidebarSectionLink.count }.by(6) expect(SidebarSectionLink.where(linkable_type: 'Category', linkable_id: category.id).pluck(:user_id)).to contain_exactly( user.id, user2.id, user3.id ) expect(SidebarSectionLink.where(linkable_type: 'Category', linkable_id: category2.id).pluck(:user_id)).to contain_exactly( user.id, user2.id, user3.id ) expect(SidebarSectionLink.where(linkable_type: 'Category', linkable_id: category3.id).pluck(:user_id)).to contain_exactly( user.id, user2.id, user3.id ) end it 'deletes and creates the right sidebar section link records when categories are added and removed' do backfiller = described_class.new( "default_sidebar_categories", previous_value: "#{category.id}|#{category2.id}", new_value: "#{category3.id}" ) original_count = SidebarSectionLink.count expect do backfiller.backfill! end.to change { SidebarSectionLink.where(linkable_type: 'Category', linkable_id: category.id).count }.by(-2) .and change { SidebarSectionLink.where(linkable_type: 'Category', linkable_id: category2.id).count }.by(-1) .and change { SidebarSectionLink.where(linkable_type: 'Category', linkable_id: category3.id).count }.by(3) expect(SidebarSectionLink.count).to eq(original_count) # Net change of 0 expect(SidebarSectionLink.where(linkable_type: 'Category', linkable_id: category3.id).pluck(:user_id)).to contain_exactly( user.id, user2.id, user3.id ) end end context 'for default_sidebar_tags setting' do it 'deletes the right sidebar section link records when tags are removed' do backfiller = described_class.new( "default_sidebar_tags", previous_value: "#{tag.name}|#{tag2.name}|#{tag3.name}", new_value: "#{tag3.name}" ) expect do backfiller.backfill! end.to change { SidebarSectionLink.count }.by(-3) expect(SidebarSectionLink.exists?(id: tag_sidebar_section_link_ids)).to eq(false) end it 'creates the right sidebar section link records when tags are added' do backfiller = described_class.new( "default_sidebar_tags", previous_value: "#{tag.name}|#{tag2.name}", new_value: "#{tag.name}|#{tag2.name}|#{tag3.name}" ) expect do backfiller.backfill! end.to change { SidebarSectionLink.count }.by(3) expect(SidebarSectionLink.where(linkable_type: 'Tag', linkable_id: tag3.id).pluck(:user_id)).to contain_exactly( user.id, user2.id, user3.id ) end it 'deletes and creates the right sidebar section link records when tags are added and removed' do backfiller = described_class.new( "default_sidebar_tags", previous_value: "#{tag.name}|#{tag2.name}", new_value: "#{tag3.name}" ) original_count = SidebarSectionLink.count expect do backfiller.backfill! end.to change { SidebarSectionLink.where(linkable_type: 'Tag', linkable_id: tag.id).count }.by(-2) .and change { SidebarSectionLink.where(linkable_type: 'Tag', linkable_id: tag2.id).count }.by(-1) .and change { SidebarSectionLink.where(linkable_type: 'Tag', linkable_id: tag3.id).count }.by(3) expect(SidebarSectionLink.count).to eq(original_count) # net change of 0 expect(SidebarSectionLink.where(linkable_type: 'Tag', linkable_id: tag3.id).pluck(:user_id)).to contain_exactly( user.id, user2.id, user3.id ) end end end describe '#number_of_users_to_backfill' do context 'for default_sidebar_categories setting' do it "returns 3 for the user count when a new category for all users is added" do backfiller = described_class.new( "default_sidebar_categories", previous_value: "", new_value: "#{category3.id}" ) expect(backfiller.number_of_users_to_backfill).to eq(3) end it "returns 2 for the user count when category which 2 users have configured in sidebar is removed" do backfiller = described_class.new( "default_sidebar_categories", previous_value: "#{category.id}|#{category2.id}", new_value: "#{category2.id}" ) expect(backfiller.number_of_users_to_backfill).to eq(2) end # category, category2 => category2, category3 it "returns 3 for the user count when a new category is added and a category is removed" do backfiller = described_class.new( "default_sidebar_categories", previous_value: "#{category.id}|#{category2.id}", new_value: "#{category2.id}|#{category3.id}" ) expect(backfiller.number_of_users_to_backfill).to eq(3) end end context 'for default_sidebar_tags setting' do it "returns 3 for the user count when a new tag for all users is added" do backfiller = described_class.new( "default_sidebar_tags", previous_value: "", new_value: "#{tag3.name}" ) expect(backfiller.number_of_users_to_backfill).to eq(3) end # tag, tag2 => tag2 it "returns 2 for the user count when tag which 2 users have configured in sidebar is removed" do backfiller = described_class.new( "default_sidebar_tags", previous_value: "#{tag.name}|#{tag2.name}", new_value: "#{tag2.name}" ) expect(backfiller.number_of_users_to_backfill).to eq(2) end # tag, tag2 => tag2, tag3 it "returns 3 for the user count when a new tag is added and a tag is removed" do backfiller = described_class.new( "default_sidebar_tags", previous_value: "#{tag.name}|#{tag2.name}", new_value: "#{tag2.name}|#{tag3.name}" ) expect(backfiller.number_of_users_to_backfill).to eq(3) end end end end