Commit e30cd780 authored by Sincheol (David) Kim's avatar Sincheol (David) Kim

Merge branch '354923-free-user-cap-checking-follow-ups' into 'master'

Move group namespace tests to group spec

See merge request gitlab-org/gitlab!82534
parents 72310845 12a7694b
......@@ -815,6 +815,529 @@ RSpec.describe Group do
end
end
shared_context 'bot user for project' do
let(:project_bot) { create(:user, :project_bot) }
before do
project.add_maintainer(project_bot)
end
end
shared_context 'bot user for group' do
let(:group_bot) { create(:user, :project_bot) }
before do
group.add_maintainer(group_bot)
end
end
describe '#billed_user_ids', :saas do
let_it_be(:bronze_plan) { create(:bronze_plan) }
let_it_be(:premium_plan) { create(:premium_plan) }
let_it_be(:group, refind: true) { create(:group) }
let_it_be(:developer) { create(:user) }
let_it_be(:guest) { create(:user) }
before_all do
group.add_developer(developer)
group.add_developer(create(:user, :blocked))
group.add_guest(guest)
create(:group_member, :awaiting, :developer, source: group)
end
subject(:billed_user_ids) { group.billed_user_ids }
shared_context 'bot user for shared_group' do
let(:group_bot_in_shared_group) { create(:user, :project_bot) }
before do
add_bot_to_group.add_maintainer(group_bot_in_shared_group)
end
end
shared_context 'bot user for invited_group' do
let(:group_bot_in_invited_group) { create(:user, :project_bot) }
before do
invited_group.add_maintainer(group_bot_in_invited_group)
end
end
it 'returns a breakdown of billable user ids' do
expect(billed_user_ids.keys).to eq([
:user_ids,
:group_member_user_ids,
:project_member_user_ids,
:shared_group_user_ids,
:shared_project_user_ids
])
end
shared_examples 'ultimate plan' do
it 'does not include guest users and only active users' do
expect(billed_user_ids[:user_ids]).to match_array([developer.id])
end
context 'when group has a project and users are invited to it' do
let_it_be(:project) { create(:project, namespace: group) }
let_it_be(:project_developer) { create(:user) }
before_all do
project.add_developer(project_developer)
project.add_guest(create(:user))
project.add_developer(developer)
project.add_developer(create(:user, :blocked))
create(:project_member, :awaiting, :developer, source: project)
end
it 'includes invited active users except guests to the group', :aggregate_failures do
expect(billed_user_ids[:user_ids]).to match_array([project_developer.id, developer.id])
expect(billed_user_ids[:project_member_user_ids]).to match_array([project_developer.id, developer.id])
expect(billed_user_ids[:group_member_user_ids]).to match_array([developer.id])
expect(billed_user_ids[:shared_group_user_ids]).to match_array([])
expect(billed_user_ids[:shared_project_user_ids]).to match_array([])
end
context 'with bot users for project' do
include_context 'bot user for project'
it { expect(billed_user_ids[:user_ids]).not_to include(project_bot.id) }
it { expect(billed_user_ids[:project_member_user_ids]).not_to include(project_bot.id) }
end
context 'with bot users for group' do
include_context 'bot user for group'
it { expect(billed_user_ids[:user_ids]).not_to include(group_bot.id) }
it { expect(billed_user_ids[:group_member_user_ids]).not_to include(group_bot.id) }
end
context 'when group is invited to the project' do
let_it_be(:invited_group) { create(:group) }
let_it_be(:invited_group_developer) { create(:user) }
before_all do
invited_group.add_developer(invited_group_developer)
invited_group.add_guest(create(:user))
invited_group.add_developer(create(:user, :blocked))
invited_group.add_developer(developer)
create(:group_member, :awaiting, :developer, source: invited_group)
end
context 'when group is invited as non guest' do
before_all do
create(:project_group_link, project: project, group: invited_group)
end
it 'includes only active users except guests of the invited groups', :aggregate_failures do
expect(billed_user_ids[:user_ids]).to match_array([invited_group_developer.id, project_developer.id, developer.id])
expect(billed_user_ids[:shared_group_user_ids]).to match_array([])
expect(billed_user_ids[:shared_project_user_ids]).to match_array([invited_group_developer.id, developer.id])
expect(billed_user_ids[:group_member_user_ids]).to match_array([developer.id])
expect(billed_user_ids[:project_member_user_ids]).to match_array([developer.id, project_developer.id])
end
context 'the invited group contains bot users' do
include_context 'bot user for invited_group'
it { expect(billed_user_ids[:user_ids]).not_to include(group_bot_in_invited_group.id) }
it { expect(billed_user_ids[:shared_project_user_ids]).not_to include(group_bot_in_invited_group.id) }
end
end
context 'when group is invited as a guest to the project' do
before do
create(:project_group_link, :guest, project: project, group: invited_group)
end
it 'does not include any members from the invited group', :aggregate_failures do
expect(billed_user_ids[:user_ids]).to match_array([project_developer.id, developer.id])
expect(billed_user_ids[:shared_project_user_ids]).to be_empty
end
end
end
end
context 'when group has been shared with another group' do
let_it_be(:shared_group) { create(:group) }
let_it_be(:shared_group_developer) { create(:user) }
before_all do
shared_group.add_developer(shared_group_developer)
shared_group.add_guest(create(:user))
shared_group.add_developer(create(:user, :blocked))
create(:group_member, :awaiting, :developer, source: shared_group)
create(:group_group_link, { shared_with_group: shared_group, shared_group: group })
end
it 'includes active users from the shared group to the billed members', :aggregate_failures do
expect(billed_user_ids[:user_ids]).to match_array([shared_group_developer.id, developer.id])
expect(billed_user_ids[:shared_group_user_ids]).to match_array([shared_group_developer.id])
expect(shared_group.billed_user_ids[:user_ids]).not_to include([developer.id])
end
context 'the shared group contains bot users' do
include_context 'bot user for shared_group' do
let(:add_bot_to_group) { shared_group }
end
it { expect(billed_user_ids[:user_ids]).not_to include(group_bot_in_shared_group.id) }
it { expect(billed_user_ids[:shared_group_user_ids]).not_to include(group_bot_in_shared_group.id) }
end
context 'when subgroup invited another group to collaborate' do
let_it_be(:another_shared_group) { create(:group) }
let_it_be(:another_shared_group_developer) { create(:user) }
before_all do
another_shared_group.add_developer(another_shared_group_developer)
another_shared_group.add_guest(create(:user))
another_shared_group.add_developer(create(:user, :blocked))
create(:group_member, :awaiting, :developer, source: another_shared_group)
end
context 'when subgroup invites another group as non guest' do
before_all do
subgroup = create(:group, parent: group)
create(:group_group_link, { shared_with_group: another_shared_group, shared_group: subgroup })
end
it 'includes all the active and non guest users from the shared group', :aggregate_failures do
expect(billed_user_ids[:user_ids]).to match_array([shared_group_developer.id, developer.id, another_shared_group_developer.id])
expect(billed_user_ids[:shared_group_user_ids]).to match_array([shared_group_developer.id, another_shared_group_developer.id])
expect(shared_group.billed_user_ids[:user_ids]).not_to include([developer.id])
expect(another_shared_group.billed_user_ids[:user_ids]).not_to include([developer.id, shared_group_developer.id])
end
context 'the shared group contains bot users' do
include_context 'bot user for shared_group' do
let(:add_bot_to_group) { another_shared_group }
end
it { expect(billed_user_ids[:user_ids]).not_to include(group_bot_in_shared_group.id) }
it { expect(billed_user_ids[:shared_group_user_ids]).not_to include(group_bot_in_shared_group.id) }
end
end
context 'when subgroup invites another group as guest' do
before do
subgroup = create(:group, parent: group)
create(:group_group_link, :guest, { shared_with_group: another_shared_group, shared_group: subgroup })
end
it 'does not include any user from the shared group from the subgroup', :aggregate_failures do
expect(billed_user_ids[:user_ids]).to match_array([shared_group_developer.id, developer.id])
expect(billed_user_ids[:shared_group_user_ids]).to match_array([shared_group_developer.id])
end
end
end
end
end
context 'with a ultimate plan' do
before_all do
create(:gitlab_subscription, :ultimate, namespace: group)
end
it_behaves_like 'ultimate plan'
end
context 'with an ultimate trial plan' do
before_all do
create(:gitlab_subscription, :ultimate_trial, namespace: group)
end
it_behaves_like 'ultimate plan'
end
context 'with other plans' do
%i[bronze_plan premium_plan].each do |plan|
subject(:billed_user_ids) { group.billed_user_ids }
it 'includes active guest users', :aggregate_failures do
create(:gitlab_subscription, namespace: group, hosted_plan: send(plan))
expect(billed_user_ids[:user_ids]).to match_array([guest.id, developer.id])
expect(billed_user_ids[:group_member_user_ids]).to match_array([guest.id, developer.id])
end
context 'when group has a project and users invited to it' do
let_it_be(:project) { create(:project, namespace: group) }
let_it_be(:project_developer) { create(:user) }
let_it_be(:project_guest) { create(:user) }
before_all do
create(:gitlab_subscription, namespace: group, hosted_plan: send(plan))
project.add_developer(project_developer)
project.add_guest(project_guest)
project.add_developer(create(:user, :blocked))
project.add_developer(developer)
create(:project_member, :awaiting, :developer, source: project)
end
it 'includes invited active users to the group', :aggregate_failures do
expect(billed_user_ids[:user_ids]).to match_array([guest.id, developer.id, project_guest.id, project_developer.id])
expect(billed_user_ids[:project_member_user_ids]).to match_array([developer.id, project_guest.id, project_developer.id])
end
context 'with bot users for project' do
include_context 'bot user for project'
it { expect(billed_user_ids[:user_ids]).not_to include(project_bot.id) }
it { expect(billed_user_ids[:project_member_user_ids]).not_to include(project_bot.id) }
end
context 'with bot users for group' do
include_context 'bot user for group'
it { expect(billed_user_ids[:user_ids]).not_to include(group_bot.id) }
it { expect(billed_user_ids[:group_member_user_ids]).not_to include(group_bot.id) }
end
context 'when group is invited to the project' do
let_it_be(:invited_group) { create(:group) }
let_it_be(:invited_group_developer) { create(:user) }
let_it_be(:invited_group_guest) { create(:user) }
before_all do
invited_group.add_developer(invited_group_developer)
invited_group.add_developer(developer)
invited_group.add_guest(invited_group_guest)
invited_group.add_developer(create(:user, :blocked))
create(:group_member, :awaiting, :developer, source: invited_group)
create(:project_group_link, project: project, group: invited_group)
end
it 'includes the unique active users and guests of the invited groups', :aggregate_failures do
expect(billed_user_ids[:user_ids]).to match_array([
guest.id,
developer.id,
project_guest.id,
project_developer.id,
invited_group_developer.id,
invited_group_guest.id
])
expect(billed_user_ids[:shared_project_user_ids]).to match_array([
developer.id,
invited_group_developer.id,
invited_group_guest.id
])
end
context 'the invited group contains bot users' do
include_context 'bot user for invited_group'
it { expect(billed_user_ids[:user_ids]).not_to include(group_bot_in_invited_group.id) }
it { expect(billed_user_ids[:shared_project_user_ids]).not_to include(group_bot_in_invited_group.id) }
end
end
end
context 'when group has been shared with another group' do
let_it_be(:shared_group, refind: true) { create(:group) }
let_it_be(:shared_group_developer) { create(:user) }
let_it_be(:shared_group_guest) { create(:user) }
before_all do
create(:gitlab_subscription, namespace: group, hosted_plan: send(plan))
shared_group.add_developer(shared_group_developer)
shared_group.add_guest(shared_group_guest)
shared_group.add_developer(create(:user, :blocked))
create(:group_member, :awaiting, :developer, source: shared_group)
create(:group_group_link, { shared_with_group: shared_group,
shared_group: group })
end
it 'includes active users from the shared group including guests', :aggregate_failures do
expect(billed_user_ids[:user_ids]).to match_array([developer.id, guest.id, shared_group_developer.id, shared_group_guest.id])
expect(billed_user_ids[:shared_group_user_ids]).to match_array([shared_group_developer.id, shared_group_guest.id])
expect(shared_group.billed_user_ids[:user_ids]).to match_array([shared_group_developer.id, shared_group_guest.id])
end
context 'the shared group contains bot users' do
include_context 'bot user for shared_group' do
let(:add_bot_to_group) { shared_group }
end
it { expect(billed_user_ids[:user_ids]).not_to include(group_bot_in_shared_group.id) }
it { expect(billed_user_ids[:shared_group_user_ids]).not_to include(group_bot_in_shared_group.id) }
end
end
end
end
end
describe '#billable_members_count', :saas do
let_it_be(:bronze_plan) { create(:bronze_plan) }
let_it_be(:premium_plan) { create(:premium_plan) }
let_it_be(:ultimate_plan) { create(:ultimate_plan) }
let_it_be(:group, refind: true) { create(:group) }
let_it_be(:developer) { create(:user) }
before_all do
group.add_developer(developer)
group.add_developer(create(:user, :blocked))
group.add_guest(create(:user))
create(:group_member, :awaiting, :developer, source: group)
end
context 'with an ultimate plan' do
before_all do
create(:gitlab_subscription, namespace: group, hosted_plan: ultimate_plan)
end
it 'counts only active users with an active membership with an access level higher than guest' do
expect(group.billable_members_count).to eq(1)
end
context 'when group has a project with invited users' do
let_it_be(:project) { create(:project, namespace: group) }
before_all do
project.add_developer(create(:user))
project.add_guest(create(:user))
project.add_developer(developer)
project.add_developer(create(:user, :blocked))
create(:project_member, :awaiting, :developer, source: project)
end
it 'includes invited active users except guests and awaiting members' do
expect(group.billable_members_count).to eq(2)
end
context 'with bot users for project and group' do
include_context 'bot user for project'
include_context 'bot user for group'
it 'does not include bot users in the count' do
expect(group.billable_members_count).to eq(2)
end
end
context 'when another group is invited to the project' do
let(:invited_group) { create(:group) }
before do
invited_group.add_developer(create(:user))
invited_group.add_guest(create(:user))
invited_group.add_developer(create(:user, :blocked))
invited_group.add_developer(developer)
create(:group_member, :awaiting, :developer, source: invited_group)
create(:project_group_link, project: project, group: invited_group)
end
it 'includes active users in the invited group with an access level higher than guest' do
expect(group.billable_members_count).to eq(3)
end
end
end
context 'when group has been shared with another group' do
let(:other_group) { create(:group) }
before do
other_group.add_developer(create(:user))
other_group.add_guest(create(:user))
other_group.add_developer(create(:user, :blocked))
create(:group_member, :awaiting, :developer, source: other_group)
create(:group_group_link, { shared_with_group: other_group, shared_group: group })
end
it 'includes active users from the other group in the billed members count' do
expect(group.billable_members_count).to eq(2)
end
end
end
context 'with other plans' do
%i[bronze_plan premium_plan].each do |plan|
it 'counts active guest users' do
create(:gitlab_subscription, namespace: group, hosted_plan: send(plan))
expect(group.billable_members_count).to eq(2)
end
context 'when group has a project and users invited to it' do
let_it_be(:project) { create(:project, namespace: group) }
before_all do
create(:gitlab_subscription, namespace: group, hosted_plan: send(plan))
project.add_developer(create(:user))
project.add_guest(create(:user))
project.add_developer(create(:user, :blocked))
project.add_developer(developer)
create(:project_member, :awaiting, :developer, source: project)
end
it 'includes invited active users to the group' do
expect(group.billable_members_count).to eq(4)
end
context 'with bot users for project and group' do
include_context 'bot user for project'
include_context 'bot user for group'
it 'does not include bot users in the count' do
expect(group.billable_members_count).to eq(4)
end
end
context 'when another group is invited to the project' do
let(:invited_group) { create(:group) }
before do
invited_group.add_developer(create(:user))
invited_group.add_developer(developer)
invited_group.add_guest(create(:user))
invited_group.add_developer(create(:user, :blocked))
create(:group_member, :awaiting, :developer, source: invited_group)
create(:project_group_link, project: project, group: invited_group)
end
it 'counts the unique active users including guests of the invited groups' do
expect(group.billable_members_count).to eq(6)
end
end
end
context 'when group has been shared with another group' do
let(:other_group) { create(:group) }
before do
create(:gitlab_subscription, namespace: group, hosted_plan: send(plan))
other_group.add_developer(create(:user))
other_group.add_guest(create(:user))
other_group.add_developer(create(:user, :blocked))
create(:group_member, :awaiting, :developer, source: other_group)
create(:group_group_link, { shared_with_group: other_group, shared_group: group })
end
it 'includes active users from the other group including guests in the billed members count' do
expect(group.billable_members_count).to eq(4)
end
end
end
end
end
describe '#free_user_cap_reached?' do
subject(:free_user_cap_reached_for_group?) { group.free_user_cap_reached? }
context 'when this group has no root ancestor' do
it_behaves_like 'returning the right value for free_user_cap_reached?' do
let_it_be(:group) { create(:group) }
let(:root_group) { group }
end
end
context 'when this group has a root ancestor' do
it_behaves_like 'returning the right value for free_user_cap_reached?' do
let_it_be(:group) { create(:group) }
let_it_be(:root_group) { create(:group, children: [group]) }
end
end
end
describe '#users_count' do
subject { group.users_count }
......
......@@ -8,10 +8,6 @@ RSpec.describe Namespace do
include EE::GeoHelpers
let(:namespace) { create(:namespace) }
let(:default_plan) { create(:default_plan) }
let(:free_plan) { create(:free_plan) }
let!(:bronze_plan) { create(:bronze_plan) }
let!(:premium_plan) { create(:premium_plan) }
let!(:ultimate_plan) { create(:ultimate_plan) }
it { is_expected.to have_one(:namespace_limit) }
......@@ -870,9 +866,7 @@ RSpec.describe Namespace do
end
context 'when free plan does exist' do
before do
free_plan
end
let!(:free_plan) { create(:free_plan) }
it 'generates a subscription' do
expect(namespace.actual_plan).to eq(free_plan)
......@@ -888,9 +882,7 @@ RSpec.describe Namespace do
let(:subgroup) { create(:group, parent: parent) }
context 'when free plan does exist' do
before do
free_plan
end
let!(:free_plan) { create(:free_plan) }
it 'does not generates a subscription' do
expect(subgroup.actual_plan).to eq(free_plan)
......@@ -968,647 +960,35 @@ RSpec.describe Namespace do
end
end
shared_context 'bot user for project' do
let(:project_bot) { create(:user, :project_bot) }
before do
project.add_maintainer(project_bot)
end
end
shared_context 'bot user for group' do
let(:group_bot) { create(:user, :project_bot) }
before do
group.add_maintainer(group_bot)
end
end
shared_context 'bot user for invited_group' do
let(:group_bot_in_invited_group) { create(:user, :project_bot) }
before do
invited_group.add_maintainer(group_bot_in_invited_group)
end
end
shared_context 'bot user for shared_group' do
let(:group_bot_in_shared_group) { create(:user, :project_bot) }
describe '#billed_user_ids' do
let(:user) { create(:user) }
before do
add_bot_to_group.add_maintainer(group_bot_in_shared_group)
it 'returns 1' do
expect(user.namespace.billed_user_ids.keys).to eq([
:user_ids,
:group_member_user_ids,
:project_member_user_ids,
:shared_group_user_ids,
:shared_project_user_ids
])
expect(user.namespace.billed_user_ids[:user_ids]).to eq([user.id])
end
end
describe '#billed_user_ids', :saas do
context 'with a user namespace' do
let(:user) { create(:user) }
it 'returns 1' do
expect(user.namespace.billed_user_ids.keys).to eq([
:user_ids,
:group_member_user_ids,
:project_member_user_ids,
:shared_group_user_ids,
:shared_project_user_ids
])
expect(user.namespace.billed_user_ids[:user_ids]).to eq([user.id])
end
end
context 'with a group namespace' do
shared_examples 'billable group plan retrieval' do
let(:group) { create(:group) }
let(:developer) { create(:user) }
let(:guest) { create(:user) }
before do
group.add_developer(developer)
group.add_developer(create(:user, :blocked))
group.add_guest(guest)
group.clear_memoization(:billed_user_ids_including_guests)
create(:group_member, :awaiting, :developer, source: group)
end
subject(:billed_user_ids) { group.billed_user_ids }
it 'returns a breakdown of billable user ids' do
expect(billed_user_ids.keys).to eq([
:user_ids,
:group_member_user_ids,
:project_member_user_ids,
:shared_group_user_ids,
:shared_project_user_ids
])
end
shared_examples 'ultimate plan' do
it 'does not include guest users and only active users' do
expect(billed_user_ids[:user_ids]).to match_array([developer.id])
end
context 'when group has a project and users are invited to it' do
let(:project) { create(:project, namespace: group) }
let(:project_developer) { create(:user) }
before do
project.add_developer(project_developer)
project.add_guest(create(:user))
project.add_developer(developer)
project.add_developer(create(:user, :blocked))
group.clear_memoization(:billed_user_ids_including_guests)
create(:project_member, :awaiting, :developer, source: project)
end
it 'includes invited active users except guests to the group', :aggregate_failures do
expect(billed_user_ids[:user_ids]).to match_array([project_developer.id, developer.id])
expect(billed_user_ids[:project_member_user_ids]).to match_array([project_developer.id, developer.id])
expect(billed_user_ids[:group_member_user_ids]).to match_array([developer.id])
expect(billed_user_ids[:shared_group_user_ids]).to match_array([])
expect(billed_user_ids[:shared_project_user_ids]).to match_array([])
end
context 'with bot users for project' do
include_context 'bot user for project'
it { expect(billed_user_ids[:user_ids]).not_to include(project_bot.id) }
it { expect(billed_user_ids[:project_member_user_ids]).not_to include(project_bot.id) }
end
context 'with bot users for group' do
include_context 'bot user for group'
it { expect(billed_user_ids[:user_ids]).not_to include(group_bot.id) }
it { expect(billed_user_ids[:group_member_user_ids]).not_to include(group_bot.id) }
end
context 'when group is invited to the project' do
let(:invited_group) { create(:group) }
let(:invited_group_developer) { create(:user) }
before do
invited_group.add_developer(invited_group_developer)
invited_group.add_guest(create(:user))
invited_group.add_developer(create(:user, :blocked))
invited_group.add_developer(developer)
group.clear_memoization(:billed_user_ids_including_guests)
create(:group_member, :awaiting, :developer, source: invited_group)
end
context 'when group is invited as non guest' do
before do
create(:project_group_link, project: project, group: invited_group)
end
it 'includes only active users except guests of the invited groups', :aggregate_failures do
expect(billed_user_ids[:user_ids]).to match_array([invited_group_developer.id, project_developer.id, developer.id])
expect(billed_user_ids[:shared_group_user_ids]).to match_array([])
expect(billed_user_ids[:shared_project_user_ids]).to match_array([invited_group_developer.id, developer.id])
expect(billed_user_ids[:group_member_user_ids]).to match_array([developer.id])
expect(billed_user_ids[:project_member_user_ids]).to match_array([developer.id, project_developer.id])
end
context 'the invited group contains bot users' do
include_context 'bot user for invited_group'
it { expect(billed_user_ids[:user_ids]).not_to include(group_bot_in_invited_group.id) }
it { expect(billed_user_ids[:shared_project_user_ids]).not_to include(group_bot_in_invited_group.id) }
end
end
context 'when group is invited as a guest to the project' do
before do
create(:project_group_link, :guest, project: project, group: invited_group)
end
it 'does not include any members from the invited group', :aggregate_failures do
expect(billed_user_ids[:user_ids]).to match_array([project_developer.id, developer.id])
expect(billed_user_ids[:shared_project_user_ids]).to be_empty
end
end
end
end
context 'when group has been shared with another group' do
let(:shared_group) { create(:group) }
let(:shared_group_developer) { create(:user) }
before do
shared_group.add_developer(shared_group_developer)
shared_group.add_guest(create(:user))
shared_group.add_developer(create(:user, :blocked))
group.clear_memoization(:billed_user_ids_including_guests)
shared_group.clear_memoization(:billed_user_ids_including_guests)
create(:group_member, :awaiting, :developer, source: shared_group)
create(:group_group_link, { shared_with_group: shared_group,
shared_group: group })
end
it 'includes active users from the shared group to the billed members', :aggregate_failures do
expect(billed_user_ids[:user_ids]).to match_array([shared_group_developer.id, developer.id])
expect(billed_user_ids[:shared_group_user_ids]).to match_array([shared_group_developer.id])
expect(shared_group.billed_user_ids[:user_ids]).not_to include([developer.id])
end
context 'the shared group contains bot users' do
include_context 'bot user for shared_group' do
let(:add_bot_to_group) { shared_group }
end
it { expect(billed_user_ids[:user_ids]).not_to include(group_bot_in_shared_group.id) }
it { expect(billed_user_ids[:shared_group_user_ids]).not_to include(group_bot_in_shared_group.id) }
end
context 'when subgroup invited another group to collaborate' do
let(:another_shared_group) { create(:group) }
let(:another_shared_group_developer) { create(:user) }
before do
another_shared_group.add_developer(another_shared_group_developer)
another_shared_group.add_guest(create(:user))
another_shared_group.add_developer(create(:user, :blocked))
group.clear_memoization(:billed_user_ids_including_guests)
create(:group_member, :awaiting, :developer, source: another_shared_group)
end
context 'when subgroup invites another group as non guest' do
before do
subgroup = create(:group, parent: group)
create(:group_group_link, { shared_with_group: another_shared_group,
shared_group: subgroup })
end
it 'includes all the active and non guest users from the shared group', :aggregate_failures do
expect(billed_user_ids[:user_ids]).to match_array([shared_group_developer.id, developer.id, another_shared_group_developer.id])
expect(billed_user_ids[:shared_group_user_ids]).to match_array([shared_group_developer.id, another_shared_group_developer.id])
expect(shared_group.billed_user_ids[:user_ids]).not_to include([developer.id])
expect(another_shared_group.billed_user_ids[:user_ids]).not_to include([developer.id, shared_group_developer.id])
end
context 'the shared group contains bot users' do
include_context 'bot user for shared_group' do
let(:add_bot_to_group) { another_shared_group }
end
it { expect(billed_user_ids[:user_ids]).not_to include(group_bot_in_shared_group.id) }
it { expect(billed_user_ids[:shared_group_user_ids]).not_to include(group_bot_in_shared_group.id) }
end
end
context 'when subgroup invites another group as guest' do
before do
subgroup = create(:group, parent: group)
create(:group_group_link, :guest, { shared_with_group: another_shared_group,
shared_group: subgroup })
end
it 'does not includes any user from the shared group from the subgroup', :aggregate_failures do
expect(billed_user_ids[:user_ids]).to match_array([shared_group_developer.id, developer.id])
expect(billed_user_ids[:shared_group_user_ids]).to match_array([shared_group_developer.id])
end
end
end
end
end
context 'with a ultimate plan' do
before do
create(:gitlab_subscription, :ultimate, namespace: group)
end
it_behaves_like 'ultimate plan'
end
context 'with an ultimate trial plan' do
before do
create(:gitlab_subscription, :ultimate_trial, namespace: group)
end
it_behaves_like 'ultimate plan'
end
context 'with other plans' do
%i[bronze_plan premium_plan].each do |plan|
subject(:billed_user_ids) { group.billed_user_ids }
it 'includes active guest users', :aggregate_failures do
create(:gitlab_subscription, namespace: group, hosted_plan: send(plan))
expect(billed_user_ids[:user_ids]).to match_array([guest.id, developer.id])
expect(billed_user_ids[:group_member_user_ids]).to match_array([guest.id, developer.id])
end
describe '#billable_members_count' do
let(:user) { create(:user) }
context 'when group has a project and users invited to it' do
let(:project) { create(:project, namespace: group) }
let(:project_developer) { create(:user) }
let(:project_guest) { create(:user) }
before do
create(:gitlab_subscription, namespace: group, hosted_plan: send(plan))
project.add_developer(project_developer)
project.add_guest(project_guest)
project.add_developer(create(:user, :blocked))
project.add_developer(developer)
group.clear_memoization(:billed_user_ids_including_guests)
create(:project_member, :awaiting, :developer, source: project)
end
it 'includes invited active users to the group', :aggregate_failures do
expect(billed_user_ids[:user_ids]).to match_array([guest.id, developer.id, project_guest.id, project_developer.id])
expect(billed_user_ids[:project_member_user_ids]).to match_array([developer.id, project_guest.id, project_developer.id])
end
context 'with bot users for project' do
include_context 'bot user for project'
it { expect(billed_user_ids[:user_ids]).not_to include(project_bot.id) }
it { expect(billed_user_ids[:project_member_user_ids]).not_to include(project_bot.id) }
end
context 'with bot users for group' do
include_context 'bot user for group'
it { expect(billed_user_ids[:user_ids]).not_to include(group_bot.id) }
it { expect(billed_user_ids[:group_member_user_ids]).not_to include(group_bot.id) }
end
context 'when group is invited to the project' do
let(:invited_group) { create(:group) }
let(:invited_group_developer) { create(:user) }
let(:invited_group_guest) { create(:user) }
before do
invited_group.add_developer(invited_group_developer)
invited_group.add_developer(developer)
invited_group.add_guest(invited_group_guest)
invited_group.add_developer(create(:user, :blocked))
group.clear_memoization(:billed_user_ids_including_guests)
create(:group_member, :awaiting, :developer, source: invited_group)
create(:project_group_link, project: project, group: invited_group)
end
it 'includes the unique active users and guests of the invited groups', :aggregate_failures do
expect(billed_user_ids[:user_ids]).to match_array([
guest.id,
developer.id,
project_guest.id,
project_developer.id,
invited_group_developer.id,
invited_group_guest.id
])
expect(billed_user_ids[:shared_project_user_ids]).to match_array([
developer.id,
invited_group_developer.id,
invited_group_guest.id
])
end
context 'the invited group contains bot users' do
include_context 'bot user for invited_group'
it { expect(billed_user_ids[:user_ids]).not_to include(group_bot_in_invited_group.id) }
it { expect(billed_user_ids[:shared_project_user_ids]).not_to include(group_bot_in_invited_group.id) }
end
end
end
context 'when group has been shared with another group' do
let(:shared_group) { create(:group) }
let(:shared_group_developer) { create(:user) }
let(:shared_group_guest) { create(:user) }
before do
create(:gitlab_subscription, namespace: group, hosted_plan: send(plan))
shared_group.add_developer(shared_group_developer)
shared_group.add_guest(shared_group_guest)
shared_group.add_developer(create(:user, :blocked))
group.clear_memoization(:billed_user_ids_including_guests)
shared_group.clear_memoization(:billed_user_ids_including_guests)
create(:group_member, :awaiting, :developer, source: shared_group)
create(:group_group_link, { shared_with_group: shared_group,
shared_group: group })
end
it 'includes active users from the shared group including guests', :aggregate_failures do
expect(billed_user_ids[:user_ids]).to match_array([developer.id, guest.id, shared_group_developer.id, shared_group_guest.id])
expect(billed_user_ids[:shared_group_user_ids]).to match_array([shared_group_developer.id, shared_group_guest.id])
expect(shared_group.billed_user_ids[:user_ids]).to match_array([shared_group_developer.id, shared_group_guest.id])
end
context 'the shared group contains bot users' do
include_context 'bot user for shared_group' do
let(:add_bot_to_group) { shared_group }
end
it { expect(billed_user_ids[:user_ids]).not_to include(group_bot_in_shared_group.id) }
it { expect(billed_user_ids[:shared_group_user_ids]).not_to include(group_bot_in_shared_group.id) }
end
end
end
end
end
it_behaves_like 'billable group plan retrieval'
end
end
describe '#billable_members_count', :saas do
context 'with a user namespace' do
let(:user) { create(:user) }
it 'returns 1' do
expect(user.namespace.billable_members_count).to eq(1)
end
end
context 'with a group namespace' do
let(:group) { create(:group) }
let(:developer) { create(:user) }
before do
group.add_developer(developer)
group.add_developer(create(:user, :blocked))
group.add_guest(create(:user))
group.clear_memoization(:billed_user_ids_including_guests)
create(:group_member, :awaiting, :developer, source: group)
end
context 'with an ultimate plan' do
before do
create(:gitlab_subscription, namespace: group, hosted_plan: ultimate_plan)
end
it 'counts only active users with an active membership with an access level higher than guest' do
expect(group.billable_members_count).to eq(1)
end
context 'when group has a project with invited users' do
let(:project) { create(:project, namespace: group) }
before do
project.add_developer(create(:user))
project.add_guest(create(:user))
project.add_developer(developer)
project.add_developer(create(:user, :blocked))
group.clear_memoization(:billed_user_ids_including_guests)
create(:project_member, :awaiting, :developer, source: project)
end
it 'includes invited active users except guests and awaiting members' do
expect(group.billable_members_count).to eq(2)
end
context 'with bot users for project and group' do
include_context 'bot user for project'
include_context 'bot user for group'
it 'does not include bot users in the count' do
expect(group.billable_members_count).to eq(2)
end
end
context 'when another group is invited to the project' do
let(:invited_group) { create(:group) }
before do
invited_group.add_developer(create(:user))
invited_group.add_guest(create(:user))
invited_group.add_developer(create(:user, :blocked))
invited_group.add_developer(developer)
group.clear_memoization(:billed_user_ids_including_guests)
create(:group_member, :awaiting, :developer, source: invited_group)
create(:project_group_link, project: project, group: invited_group)
end
it 'includes active users in the invited group with an access level higher than guest' do
expect(group.billable_members_count).to eq(3)
end
end
end
context 'when group has been shared with another group' do
let(:other_group) { create(:group) }
before do
other_group.add_developer(create(:user))
other_group.add_guest(create(:user))
other_group.add_developer(create(:user, :blocked))
group.clear_memoization(:billed_user_ids_including_guests)
create(:group_member, :awaiting, :developer, source: other_group)
create(:group_group_link, { shared_with_group: other_group,
shared_group: group })
end
it 'includes active users from the other group in the billed members count' do
expect(group.billable_members_count).to eq(2)
end
end
end
context 'with other plans' do
%i[bronze_plan premium_plan].each do |plan|
it 'counts active guest users' do
create(:gitlab_subscription, namespace: group, hosted_plan: send(plan))
expect(group.billable_members_count).to eq(2)
end
context 'when group has a project and users invited to it' do
let(:project) { create(:project, namespace: group) }
before do
create(:gitlab_subscription, namespace: group, hosted_plan: send(plan))
project.add_developer(create(:user))
project.add_guest(create(:user))
project.add_developer(create(:user, :blocked))
project.add_developer(developer)
group.clear_memoization(:billed_user_ids_including_guests)
create(:project_member, :awaiting, :developer, source: project)
end
it 'includes invited active users to the group' do
expect(group.billable_members_count).to eq(4)
end
context 'with bot users for project and group' do
include_context 'bot user for project'
include_context 'bot user for group'
it 'does not include bot users in the count' do
expect(group.billable_members_count).to eq(4)
end
end
context 'when another group is invited to the project' do
let(:invited_group) { create(:group) }
before do
invited_group.add_developer(create(:user))
invited_group.add_developer(developer)
invited_group.add_guest(create(:user))
invited_group.add_developer(create(:user, :blocked))
group.clear_memoization(:billed_user_ids_including_guests)
create(:group_member, :awaiting, :developer, source: invited_group)
create(:project_group_link, project: project, group: invited_group)
end
it 'counts the unique active users including guests of the invited groups' do
expect(group.billable_members_count).to eq(6)
end
end
end
context 'when group has been shared with another group' do
let(:other_group) { create(:group) }
before do
create(:gitlab_subscription, namespace: group, hosted_plan: send(plan))
other_group.add_developer(create(:user))
other_group.add_guest(create(:user))
other_group.add_developer(create(:user, :blocked))
group.clear_memoization(:billed_user_ids_including_guests)
create(:group_member, :awaiting, :developer, source: other_group)
create(:group_group_link, { shared_with_group: other_group,
shared_group: group })
end
it 'includes active users from the other group including guests in the billed members count' do
expect(group.billable_members_count).to eq(4)
end
end
end
end
it 'returns 1' do
expect(user.namespace.billable_members_count).to eq(1)
end
end
describe '#free_user_cap_reached?' do
let(:group) { create(:group) }
subject(:free_user_cap_reached_for_group?) { group.free_user_cap_reached? }
context 'when free user cap feature is not applied' do
before do
allow(group).to receive(:apply_free_user_cap?).and_return(false)
end
it { is_expected.to be_falsey }
end
context 'when free user cap feature is applied' do
before do
allow(group).to receive(:apply_free_user_cap?).and_return(true)
end
context 'when the :saas_user_caps feature flag is not enabled' do
it { is_expected.to be_falsey }
end
context 'when the :free_user_cap feature flag is enabled' do
before do
stub_feature_flags(free_user_cap: true)
end
let(:free_plan) { false }
shared_examples 'returning the right value for free_user_cap_reached?' do
before do
allow(root_group).to receive(:apply_free_user_cap?).and_return(true)
allow(root_group).to receive(:has_free_or_no_subscription?).and_return(free_plan)
end
context 'when no free user cap has been set to that root ancestor' do
it { is_expected.to be_falsey }
end
context 'when a free user cap has been set to that root ancestor' do
let(:free_plan) { true }
before do
allow(root_group).to receive(:free_plan_members_count).and_return(free_plan_members_count)
allow(group).to receive(:root_ancestor).and_return(root_group)
end
context 'when the free cap is higher than the number of billable members' do
let(:free_plan_members_count) { 3 }
it { is_expected.to be_falsey }
end
context 'when the free cap is the same as the number of billable members' do
let(:free_plan_members_count) { ::Plan::FREE_USER_LIMIT }
it { is_expected.to be_truthy }
end
context 'when the free cap is lower than the number of billable members' do
let(:free_plan_members_count) { 6 }
it { is_expected.to be_truthy }
end
end
end
context 'when this is a user namespace' do
it_behaves_like 'returning the right value for free_user_cap_reached?' do
let(:root_group) { create(:user).namespace }
end
end
context 'when this group has no root ancestor' do
it_behaves_like 'returning the right value for free_user_cap_reached?' do
let(:root_group) { group }
end
end
context 'when this group has a root ancestor' do
it_behaves_like 'returning the right value for free_user_cap_reached?' do
let(:root_group) { create(:group, children: [group]) }
end
end
end
it_behaves_like 'returning the right value for free_user_cap_reached?' do
let_it_be(:group) { create(:user).namespace }
let(:root_group) { group }
end
end
......
# frozen_string_literal: true
RSpec.shared_examples 'returning the right value for free_user_cap_reached?' do
context 'when free user cap feature is not applied' do
before do
allow(group).to receive(:apply_free_user_cap?).and_return(false)
end
it { is_expected.to be_falsey }
end
context 'when free user cap feature is applied' do
before do
allow(group).to receive(:apply_free_user_cap?).and_return(true)
end
context 'when the :saas_user_caps feature flag is not enabled' do
it { is_expected.to be_falsey }
end
context 'when the :free_user_cap feature flag is enabled' do
before do
stub_feature_flags(free_user_cap: true)
allow(root_group).to receive(:apply_free_user_cap?).and_return(true)
allow(root_group).to receive(:has_free_or_no_subscription?).and_return(free_plan)
end
let(:free_plan) { false }
context 'when no free user cap has been set to that root ancestor' do
it { is_expected.to be_falsey }
end
context 'when a free user cap has been set to that root ancestor' do
let(:free_plan) { true }
before do
allow(root_group).to receive(:free_plan_members_count).and_return(free_plan_members_count)
allow(group).to receive(:root_ancestor).and_return(root_group)
end
context 'when the free cap is higher than the number of billable members' do
let(:free_plan_members_count) { 3 }
it { is_expected.to be_falsey }
end
context 'when the free cap is the same as the number of billable members' do
let(:free_plan_members_count) { ::Plan::FREE_USER_LIMIT }
it { is_expected.to be_truthy }
end
context 'when the free cap is lower than the number of billable members' do
let(:free_plan_members_count) { 6 }
it { is_expected.to be_truthy }
end
end
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment