gitlab-ce/spec/models/concerns/members/enumerable_spec.rb

125 lines
3.8 KiB
Ruby

# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Members::Enumerable, feature_category: :groups_and_projects do
using RSpec::Parameterized::TableSyntax
before_all do
ActiveRecord::Schema.define do
create_table :_test_member_sources, force: true
end
end
before do
stub_const('TestMemberSource', klass)
# rubocop:disable RSpec/AnyInstanceOf -- stub all instances, hooks and notifications are irrelevant to the tests.
allow_any_instance_of(SystemHooksService).to receive(:execute_hooks_for)
allow_any_instance_of(Member).to receive_messages(notifiable?: false, send_request: nil)
# rubocop:enable RSpec/AnyInstanceOf
end
let_it_be(:klass) do
Class.new(Namespace) do
include Members::Enumerable
self.table_name = '_test_member_sources'
has_many :members, dependent: :destroy, as: :source, class_name: '::Member'
end
end
let_it_be(:source) { create(:namespace).becomes(klass) } # rubocop: disable Cop/AvoidBecomes -- easier to reuse existing factory object for a dummy model
let!(:owner) { create(:member, :owner, source: source).user }
let!(:guest) { create(:member, :guest, source: source).user }
let!(:requested) { create(:member, :access_request, source: source).user }
let!(:invited) { create(:member, :invited, source: source, user: create(:user)).user }
shared_context 'with parametrized filters table' do
where(:filters, :selected) do
nil | [ref(:owner), ref(:guest)]
{ access_level: Gitlab::Access::OWNER } | [ref(:owner)]
{ access_level: Gitlab::Access::GUEST } | [ref(:guest)]
end
end
shared_examples 'extract value from selected members only' do |column|
it 'extracted value from selected members' do
expected_values = selected.map { |user| user.public_send(column) }
expect(values).to contain_exactly(*expected_values)
end
it 'skips members with access request' do
expect(values).not_to include(requested.public_send(column))
end
it 'skips invited members' do
expect(values).not_to include(invited.public_send(column))
end
end
describe '#each_member_user' do
include_context 'with parametrized filters table'
with_them do
subject(:users) do
users = []
source.each_member_user(filters) { |user| users << user }
users
end
it 'iterates over selected members' do
expect(users).to contain_exactly(*selected)
end
it 'skips members with access request' do
expect(users).not_to include(requested)
end
it 'skips invited members' do
expect(users).not_to include(invited)
end
end
end
describe '#map_member_user' do
include_context 'with parametrized filters table'
with_them do
subject(:values) { source.map_member_user(filters, &:name) }
it_behaves_like 'extract value from selected members only', :name
end
end
describe '#pluck_member_user' do
include_context 'with parametrized filters table'
with_them do
context 'when single column passed' do
subject(:values) { source.pluck_member_user(:name, filters: filters) }
it_behaves_like 'extract value from selected members only', :name
end
context 'when multiple column passed' do
subject(:values) { source.pluck_member_user(:name, :email, filters: filters) }
it 'extract multiple values from selected members' do
expected_values = selected.map { |user| [user.name, user.email] }
expect(values).to contain_exactly(*expected_values)
end
it 'skips members with access request' do
expect(values).not_to include([requested.name, requested.email])
end
it 'skips invited members' do
expect(values).not_to include([invited.name, invited.email])
end
end
end
end
end