require 'spec_helper' describe 'Issuable counts caching', :use_clean_rails_memory_store_caching do let!(:member) { create(:user) } let!(:member_2) { create(:user) } let!(:non_member) { create(:user) } let!(:project) { create(:project, :public) } let!(:open_issue) { create(:issue, project: project) } let!(:confidential_issue) { create(:issue, :confidential, project: project, author: non_member) } let!(:closed_issue) { create(:issue, :closed, project: project) } before do project.add_developer(member) project.add_developer(member_2) end it 'caches issuable counts correctly for non-members' do # We can't use expect_any_instance_of because that uses a single instance. counts = 0 allow_any_instance_of(IssuesFinder).to receive(:count_by_state).and_wrap_original do |m, *args| counts += 1 m.call(*args) end aggregate_failures 'only counts once on first load with no params, and caches for later loads' do expect { visit project_issues_path(project) } .to change { counts }.by(1) expect { visit project_issues_path(project) } .not_to change { counts } end aggregate_failures 'uses counts from cache on load from non-member' do sign_in(non_member) expect { visit project_issues_path(project) } .not_to change { counts } sign_out(non_member) end aggregate_failures 'does not use the same cache for a member' do sign_in(member) expect { visit project_issues_path(project) } .to change { counts }.by(1) sign_out(member) end aggregate_failures 'uses the same cache for all members' do sign_in(member_2) expect { visit project_issues_path(project) } .not_to change { counts } sign_out(member_2) end aggregate_failures 'shares caches when params are passed' do expect { visit project_issues_path(project, author_username: non_member.username) } .to change { counts }.by(1) sign_in(member) expect { visit project_issues_path(project, author_username: non_member.username) } .to change { counts }.by(1) sign_in(non_member) expect { visit project_issues_path(project, author_username: non_member.username) } .not_to change { counts } sign_in(member_2) expect { visit project_issues_path(project, author_username: non_member.username) } .not_to change { counts } sign_out(member_2) end aggregate_failures 'resets caches on issue close' do Issues::CloseService.new(project, member).execute(open_issue) expect { visit project_issues_path(project) } .to change { counts }.by(1) sign_in(member) expect { visit project_issues_path(project) } .to change { counts }.by(1) sign_in(non_member) expect { visit project_issues_path(project) } .not_to change { counts } sign_in(member_2) expect { visit project_issues_path(project) } .not_to change { counts } sign_out(member_2) end aggregate_failures 'does not reset caches on issue update' do Issues::UpdateService.new(project, member, title: 'new title').execute(open_issue) expect { visit project_issues_path(project) } .not_to change { counts } sign_in(member) expect { visit project_issues_path(project) } .not_to change { counts } sign_in(non_member) expect { visit project_issues_path(project) } .not_to change { counts } sign_in(member_2) expect { visit project_issues_path(project) } .not_to change { counts } sign_out(member_2) end end end