Commit 8fadde83 authored by Peter Hegman's avatar Peter Hegman Committed by Etienne Baqué

Update feature specs for new project members view

Behind the `vue_project_members_list` feature flag
parent 5c5650e9
...@@ -3,13 +3,13 @@ ...@@ -3,13 +3,13 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe 'Projects > Audit Events', :js do RSpec.describe 'Projects > Audit Events', :js do
include Spec::Support::Helpers::Features::MembersHelpers
let(:user) { create(:user) } let(:user) { create(:user) }
let(:pete) { create(:user, name: 'Pete') } let(:pete) { create(:user, name: 'Pete') }
let(:project) { create(:project, :repository, namespace: user.namespace) } let(:project) { create(:project, :repository, namespace: user.namespace) }
before do before do
stub_feature_flags(vue_project_members_list: false)
project.add_maintainer(user) project.add_maintainer(user)
sign_in(user) sign_in(user)
end end
...@@ -109,6 +109,33 @@ RSpec.describe 'Projects > Audit Events', :js do ...@@ -109,6 +109,33 @@ RSpec.describe 'Projects > Audit Events', :js do
project.add_developer(pete) project.add_developer(pete)
end end
context 'when `vue_project_members_list` feature flag is enabled' do
it "appears in the project's audit events" do
visit project_project_members_path(project)
page.within find_member_row(pete) do
click_button 'Developer'
click_button 'Maintainer'
end
page.within('.qa-project-sidebar') do
find(:link, text: 'Security & Compliance').click
click_link 'Audit Events'
end
page.within('.audit-log-table') do
expect(page).to have_content 'Changed access level from Developer to Maintainer'
expect(page).to have_content(project.owner.name)
expect(page).to have_content('Pete')
end
end
end
context 'when `vue_project_members_list` feature flag is disabled' do
before do
stub_feature_flags(vue_project_members_list: false)
end
it "appears in the project's audit events" do it "appears in the project's audit events" do
visit project_project_members_path(project) visit project_project_members_path(project)
...@@ -131,6 +158,7 @@ RSpec.describe 'Projects > Audit Events', :js do ...@@ -131,6 +158,7 @@ RSpec.describe 'Projects > Audit Events', :js do
end end
end end
end end
end
describe 'changing merge request approval permission for authors and reviewers' do describe 'changing merge request approval permission for authors and reviewers' do
before do before do
......
...@@ -5,12 +5,12 @@ require 'spec_helper' ...@@ -5,12 +5,12 @@ require 'spec_helper'
RSpec.describe 'Project > Members > Invite group and members', :js do RSpec.describe 'Project > Members > Invite group and members', :js do
include Select2Helper include Select2Helper
include ActionView::Helpers::DateHelper include ActionView::Helpers::DateHelper
include Spec::Support::Helpers::Features::MembersHelpers
let(:maintainer) { create(:user) } let(:maintainer) { create(:user) }
before do before do
stub_feature_flags(invite_members_group_modal: false) stub_feature_flags(invite_members_group_modal: false)
stub_feature_flags(vue_project_members_list: false)
end end
describe 'Share group lock' do describe 'Share group lock' do
...@@ -71,7 +71,30 @@ RSpec.describe 'Project > Members > Invite group and members', :js do ...@@ -71,7 +71,30 @@ RSpec.describe 'Project > Members > Invite group and members', :js do
context 'when the group has "Share with group lock" and "Member lock" disabled' do context 'when the group has "Share with group lock" and "Member lock" disabled' do
it_behaves_like 'the project can be shared with groups and members' it_behaves_like 'the project can be shared with groups and members'
it 'the project can be shared with another group' do context 'when `vue_project_members_list` feature flag is enabled' do
it 'allows the project to be shared with another group' do
visit project_project_members_path(project)
click_on 'invite-group-tab'
select2 group_to_share_with.id, from: '#link_group_id'
page.find('body').click
find('.btn-success').click
click_link 'Groups'
page.within(members_table) do
expect(page).to have_content(group_to_share_with.name)
end
end
end
context 'when `vue_project_members_list` feature flag is disabled' do
before do
stub_feature_flags(vue_project_members_list: false)
end
it 'allows the project to be shared with another group' do
visit project_project_members_path(project) visit project_project_members_path(project)
click_on 'invite-group-tab' click_on 'invite-group-tab'
...@@ -87,6 +110,7 @@ RSpec.describe 'Project > Members > Invite group and members', :js do ...@@ -87,6 +110,7 @@ RSpec.describe 'Project > Members > Invite group and members', :js do
end end
end end
end end
end
context 'when the group has "Share with group lock" enabled' do context 'when the group has "Share with group lock" enabled' do
before do before do
......
...@@ -8,10 +8,50 @@ RSpec.describe 'Projects > Members > Member is removed from project' do ...@@ -8,10 +8,50 @@ RSpec.describe 'Projects > Members > Member is removed from project' do
let(:other_user) { create(:user) } let(:other_user) { create(:user) }
before do before do
stub_feature_flags(vue_project_members_list: false)
project.add_maintainer(user) project.add_maintainer(user)
project.add_maintainer(other_user) project.add_maintainer(other_user)
end
context 'when `vue_project_members_list` feature flag is enabled', :js do
before do
sign_in(user)
visit project_project_members_path(project)
end
it 'user is removed from project' do
click_button 'Leave'
page.within('[role="dialog"]') do
click_button('Leave')
end
expect(project.users.exists?(user.id)).to be_falsey
end
context 'when the user has been specifically allowed to access a protected branch' do
let!(:matching_protected_branch) { create(:protected_branch, authorize_user_to_push: user, authorize_user_to_merge: user, project: project) }
let!(:non_matching_protected_branch) { create(:protected_branch, authorize_user_to_push: other_user, authorize_user_to_merge: other_user, project: project) }
it 'user leaves project' do
click_button 'Leave'
page.within('[role="dialog"]') do
click_button('Leave')
end
expect(project.users.exists?(user.id)).to be_falsey
expect(matching_protected_branch.push_access_levels.where(user: user)).not_to exist
expect(matching_protected_branch.merge_access_levels.where(user: user)).not_to exist
expect(non_matching_protected_branch.push_access_levels.where(user: other_user)).to exist
expect(non_matching_protected_branch.merge_access_levels.where(user: other_user)).to exist
end
end
end
context 'when `vue_project_members_list` feature flag is disabled' do
before do
stub_feature_flags(vue_project_members_list: false)
sign_in(user) sign_in(user)
visit project_project_members_path(project) visit project_project_members_path(project)
end end
...@@ -36,4 +76,5 @@ RSpec.describe 'Projects > Members > Member is removed from project' do ...@@ -36,4 +76,5 @@ RSpec.describe 'Projects > Members > Member is removed from project' do
expect(non_matching_protected_branch.merge_access_levels.where(user: other_user)).to exist expect(non_matching_protected_branch.merge_access_levels.where(user: other_user)).to exist
end end
end end
end
end end
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe "Admin::Projects" do RSpec.describe "Admin::Projects" do
include Spec::Support::Helpers::Features::MembersHelpers
include Select2Helper include Select2Helper
let(:user) { create :user } let(:user) { create :user }
...@@ -10,8 +11,6 @@ RSpec.describe "Admin::Projects" do ...@@ -10,8 +11,6 @@ RSpec.describe "Admin::Projects" do
let(:current_user) { create(:admin) } let(:current_user) { create(:admin) }
before do before do
stub_feature_flags(vue_project_members_list: false)
sign_in(current_user) sign_in(current_user)
gitlab_enable_admin_mode_sign_in(current_user) gitlab_enable_admin_mode_sign_in(current_user)
end end
...@@ -93,13 +92,63 @@ RSpec.describe "Admin::Projects" do ...@@ -93,13 +92,63 @@ RSpec.describe "Admin::Projects" do
end end
end end
describe 'add admin himself to a project' do context 'when `vue_project_members_list` feature flag is enabled', :js do
describe 'admin adds themselves to the project' do
before do before do
project.add_maintainer(user) project.add_maintainer(user)
stub_feature_flags(invite_members_group_modal: false) stub_feature_flags(invite_members_group_modal: false)
end end
it 'adds admin a to a project as developer', :js do it 'adds admin to the project as developer', :js do
visit project_project_members_path(project)
page.within '.invite-users-form' do
select2(current_user.id, from: '#user_ids', multiple: true)
select 'Developer', from: 'access_level'
end
click_button 'Invite'
expect(find_member_row(current_user)).to have_content('Developer')
end
end
describe 'admin removes themselves from the project' do
before do
project.add_maintainer(user)
project.add_developer(current_user)
end
it 'removes admin from the project' do
visit project_project_members_path(project)
expect(find_member_row(current_user)).to have_content('Developer')
page.within find_member_row(current_user) do
click_button 'Leave'
end
page.within('[role="dialog"]') do
click_button('Leave')
end
expect(current_path).to match dashboard_projects_path
end
end
end
context 'when `vue_project_members_list` feature flag is disabled' do
before do
stub_feature_flags(vue_project_members_list: false)
end
describe 'admin adds themselves to the project' do
before do
project.add_maintainer(user)
stub_feature_flags(invite_members_group_modal: false)
end
it 'adds admin to the project as developer', :js do
visit project_project_members_path(project) visit project_project_members_path(project)
page.within '.invite-users-form' do page.within '.invite-users-form' do
...@@ -116,7 +165,7 @@ RSpec.describe "Admin::Projects" do ...@@ -116,7 +165,7 @@ RSpec.describe "Admin::Projects" do
end end
end end
describe 'admin remove himself from a project' do describe 'admin removes themselves from the project' do
before do before do
project.add_maintainer(user) project.add_maintainer(user)
project.add_developer(current_user) project.add_developer(current_user)
...@@ -135,4 +184,5 @@ RSpec.describe "Admin::Projects" do ...@@ -135,4 +184,5 @@ RSpec.describe "Admin::Projects" do
expect(page).not_to have_selector(:css, '.content-list') expect(page).not_to have_selector(:css, '.content-list')
end end
end end
end
end end
...@@ -3,17 +3,30 @@ ...@@ -3,17 +3,30 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe 'Projects > Members > Anonymous user sees members' do RSpec.describe 'Projects > Members > Anonymous user sees members' do
include Spec::Support::Helpers::Features::MembersHelpers
let(:user) { create(:user) } let(:user) { create(:user) }
let(:group) { create(:group, :public) } let(:group) { create(:group, :public) }
let(:project) { create(:project, :public) } let(:project) { create(:project, :public) }
before do before do
stub_feature_flags(vue_project_members_list: false)
project.add_maintainer(user) project.add_maintainer(user)
create(:project_group_link, project: project, group: group) create(:project_group_link, project: project, group: group)
end end
context 'when `vue_project_members_list` feature flag is enabled', :js do
it "anonymous user visits the project's members page and sees the list of members" do
visit project_project_members_path(project)
expect(find_member_row(user)).to have_content(user.name)
end
end
context 'when `vue_project_members_list` feature flag is disabled' do
before do
stub_feature_flags(vue_project_members_list: false)
end
it "anonymous user visits the project's members page and sees the list of members" do it "anonymous user visits the project's members page and sees the list of members" do
visit project_project_members_path(project) visit project_project_members_path(project)
...@@ -21,4 +34,5 @@ RSpec.describe 'Projects > Members > Anonymous user sees members' do ...@@ -21,4 +34,5 @@ RSpec.describe 'Projects > Members > Anonymous user sees members' do
project_project_members_path(project)) project_project_members_path(project))
expect(page).to have_content(user.name) expect(page).to have_content(user.name)
end end
end
end end
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe 'Projects members', :js do RSpec.describe 'Projects members', :js do
include Spec::Support::Helpers::Features::MembersHelpers
let(:user) { create(:user) } let(:user) { create(:user) }
let(:developer) { create(:user) } let(:developer) { create(:user) }
let(:group) { create(:group, :public) } let(:group) { create(:group, :public) }
...@@ -13,13 +15,111 @@ RSpec.describe 'Projects members', :js do ...@@ -13,13 +15,111 @@ RSpec.describe 'Projects members', :js do
let(:group_requester) { create(:user) } let(:group_requester) { create(:user) }
before do before do
stub_feature_flags(vue_project_members_list: false)
project.add_developer(developer) project.add_developer(developer)
group.add_owner(user) group.add_owner(user)
sign_in(user) sign_in(user)
end end
context 'when `vue_project_members_list` feature flag is enabled' do
context 'with a group invitee' do
before do
group_invitee
visit project_project_members_path(project)
end
it 'does not appear in the project members page' do
expect(members_table).not_to have_content('test2@abc.com')
end
end
context 'with a group' do
it 'shows group and project members by default' do
visit project_project_members_path(project)
expect(members_table).to have_content(developer.name)
expect(members_table).to have_content(user.name)
expect(members_table).to have_content(group.name)
end
it 'shows project members only if requested' do
visit project_project_members_path(project, with_inherited_permissions: 'exclude')
expect(members_table).to have_content(developer.name)
expect(members_table).not_to have_content(user.name)
expect(members_table).not_to have_content(group.name)
end
it 'shows group members only if requested' do
visit project_project_members_path(project, with_inherited_permissions: 'only')
expect(members_table).not_to have_content(developer.name)
expect(members_table).to have_content(user.name)
expect(members_table).to have_content(group.name)
end
end
context 'with a group, a project invitee, and a project requester' do
before do
group.request_access(group_requester)
project.request_access(project_requester)
group_invitee
project_invitee
visit project_project_members_path(project)
end
it 'shows the group owner' do
expect(members_table).to have_content(user.name)
expect(members_table).to have_content(group.name)
end
it 'shows the project developer' do
expect(members_table).to have_content(developer.name)
end
it 'shows the project invitee' do
click_link 'Invited'
expect(members_table).to have_content('test1@abc.com')
expect(members_table).not_to have_content('test2@abc.com')
end
it 'shows the project requester' do
click_link 'Access requests'
expect(members_table).to have_content(project_requester.name)
expect(members_table).not_to have_content(group_requester.name)
end
end
context 'with a group requester' do
before do
stub_feature_flags(invite_members_group_modal: false)
group.request_access(group_requester)
visit project_project_members_path(project)
end
it 'does not appear in the project members page' do
expect(page).not_to have_link('Access requests')
expect(members_table).not_to have_content(group_requester.name)
end
end
context 'showing status of members' do
it 'shows the status' do
create(:user_status, user: user, emoji: 'smirk', message: 'Authoring this object')
visit project_project_members_path(project)
expect(first_row).to have_selector('gl-emoji[data-name="smirk"]')
end
end
end
context 'when `vue_project_members_list` feature flag is disabled' do
before do
stub_feature_flags(vue_project_members_list: false)
end
context 'with a group invitee' do context 'with a group invitee' do
before do before do
group_invitee group_invitee
...@@ -126,11 +226,12 @@ RSpec.describe 'Projects members', :js do ...@@ -126,11 +226,12 @@ RSpec.describe 'Projects members', :js do
end end
end end
describe 'showing status of members' do context 'showing status of members' do
it_behaves_like 'showing user status' do it_behaves_like 'showing user status' do
let(:user_with_status) { developer } let(:user_with_status) { developer }
subject { visit project_project_members_path(project) } subject { visit project_project_members_path(project) }
end end
end end
end
end end
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe 'Projects > Members > Groups with access list', :js do RSpec.describe 'Projects > Members > Groups with access list', :js do
include Spec::Support::Helpers::Features::MembersHelpers
let_it_be(:user) { create(:user) } let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group, :public) } let_it_be(:group) { create(:group, :public) }
let_it_be(:project) { create(:project, :public) } let_it_be(:project) { create(:project, :public) }
...@@ -11,12 +13,95 @@ RSpec.describe 'Projects > Members > Groups with access list', :js do ...@@ -11,12 +13,95 @@ RSpec.describe 'Projects > Members > Groups with access list', :js do
let!(:group_link) { create(:project_group_link, project: project, group: group, **additional_link_attrs) } let!(:group_link) { create(:project_group_link, project: project, group: group, **additional_link_attrs) }
before do before do
stub_feature_flags(vue_project_members_list: false)
travel_to Time.now.utc.beginning_of_day travel_to Time.now.utc.beginning_of_day
project.add_maintainer(user) project.add_maintainer(user)
sign_in(user) sign_in(user)
end
context 'when `vue_project_members_list` feature flag is enabled' do
before do
visit project_project_members_path(project)
click_groups_tab
end
it 'updates group access level' do
click_button group_link.human_access
click_button 'Guest'
wait_for_requests
visit project_project_members_path(project)
click_groups_tab
expect(find_group_row(group)).to have_content('Guest')
end
it 'updates expiry date' do
page.within find_group_row(group) do
fill_in 'Expiration date', with: 5.days.from_now.to_date
find_field('Expiration date').native.send_keys :enter
wait_for_requests
expect(page).to have_content(/in \d days/)
end
end
context 'when link has expiry date set' do
let(:additional_link_attrs) { { expires_at: 5.days.from_now.to_date } }
it 'clears expiry date' do
page.within find_group_row(group) do
expect(page).to have_content(/in \d days/)
find('[data-testid="clear-button"]').click
wait_for_requests
expect(page).to have_content('No expiration set')
end
end
end
it 'deletes group link' do
expect(page).to have_content(group.full_name)
page.within find_group_row(group) do
click_button 'Remove group'
end
page.within('[role="dialog"]') do
click_button('Remove group')
end
expect(page).not_to have_content(group.full_name)
end
context 'search in existing members' do
it 'finds no results' do
fill_in_filtered_search 'Search groups', with: 'testing 123'
click_groups_tab
expect(page).not_to have_content(group.full_name)
end
it 'finds results' do
fill_in_filtered_search 'Search groups', with: group.full_name
click_groups_tab
expect(members_table).to have_content(group.full_name)
end
end
end
context 'when `vue_project_members_list` feature flag is disabled' do
before do
stub_feature_flags(vue_project_members_list: false)
visit project_project_members_path(project) visit project_project_members_path(project)
click_groups_tab click_groups_tab
end end
...@@ -99,6 +184,7 @@ RSpec.describe 'Projects > Members > Groups with access list', :js do ...@@ -99,6 +184,7 @@ RSpec.describe 'Projects > Members > Groups with access list', :js do
expect(page).to have_selector('.group_member', count: 1) expect(page).to have_selector('.group_member', count: 1)
end end
end end
end
def click_groups_tab def click_groups_tab
click_link 'Groups' click_link 'Groups'
......
...@@ -5,12 +5,12 @@ require 'spec_helper' ...@@ -5,12 +5,12 @@ require 'spec_helper'
RSpec.describe 'Project > Members > Invite group', :js do RSpec.describe 'Project > Members > Invite group', :js do
include Select2Helper include Select2Helper
include ActionView::Helpers::DateHelper include ActionView::Helpers::DateHelper
include Spec::Support::Helpers::Features::MembersHelpers
let(:maintainer) { create(:user) } let(:maintainer) { create(:user) }
before do before do
stub_feature_flags(invite_members_group_modal: false) stub_feature_flags(invite_members_group_modal: false)
stub_feature_flags(vue_project_members_list: false)
end end
describe 'Share with group lock' do describe 'Share with group lock' do
...@@ -41,6 +41,29 @@ RSpec.describe 'Project > Members > Invite group', :js do ...@@ -41,6 +41,29 @@ RSpec.describe 'Project > Members > Invite group', :js do
context 'when the group has "Share with group lock" disabled' do context 'when the group has "Share with group lock" disabled' do
it_behaves_like 'the project can be shared with groups' it_behaves_like 'the project can be shared with groups'
context 'when `vue_project_members_list` feature flag is enabled' do
it 'the project can be shared with another group' do
visit project_project_members_path(project)
expect(page).not_to have_link 'Groups'
click_on 'invite-group-tab'
select2 group_to_share_with.id, from: '#link_group_id'
page.find('body').click
find('.btn-success').click
click_link 'Groups'
expect(members_table).to have_content(group_to_share_with.name)
end
end
context 'when `vue_project_members_list` feature flag is disabled' do
before do
stub_feature_flags(vue_project_members_list: false)
end
it 'the project can be shared with another group' do it 'the project can be shared with another group' do
visit project_project_members_path(project) visit project_project_members_path(project)
...@@ -59,6 +82,7 @@ RSpec.describe 'Project > Members > Invite group', :js do ...@@ -59,6 +82,7 @@ RSpec.describe 'Project > Members > Invite group', :js do
end end
end end
end end
end
context 'when the group has "Share with group lock" enabled' do context 'when the group has "Share with group lock" enabled' do
before do before do
...@@ -122,7 +146,7 @@ RSpec.describe 'Project > Members > Invite group', :js do ...@@ -122,7 +146,7 @@ RSpec.describe 'Project > Members > Invite group', :js do
freeze_time { example.run } freeze_time { example.run }
end end
before do def setup
project.add_maintainer(maintainer) project.add_maintainer(maintainer)
group.add_guest(maintainer) group.add_guest(maintainer)
sign_in(maintainer) sign_in(maintainer)
...@@ -133,12 +157,28 @@ RSpec.describe 'Project > Members > Invite group', :js do ...@@ -133,12 +157,28 @@ RSpec.describe 'Project > Members > Invite group', :js do
select2 group.id, from: '#link_group_id' select2 group.id, from: '#link_group_id'
fill_in 'expires_at_groups', with: (Time.now + 4.5.days).strftime('%Y-%m-%d') fill_in 'expires_at_groups', with: 5.days.from_now.strftime('%Y-%m-%d')
click_on 'invite-group-tab' click_on 'invite-group-tab'
find('.btn-success').click find('.btn-success').click
end end
context 'when `vue_project_members_list` feature flag is enabled' do
it 'the group link shows the expiration time with a warning class' do it 'the group link shows the expiration time with a warning class' do
setup
click_link 'Groups'
expect(find_group_row(group)).to have_content(/in \d days/)
expect(find_group_row(group)).to have_selector('.gl-text-orange-500')
end
end
context 'when `vue_project_members_list` feature flag is disabled' do
before do
stub_feature_flags(vue_project_members_list: false)
end
it 'the group link shows the expiration time with a warning class' do
setup
click_link 'Groups' click_link 'Groups'
page.within('[data-testid="project-member-groups"]') do page.within('[data-testid="project-member-groups"]') do
...@@ -150,6 +190,7 @@ RSpec.describe 'Project > Members > Invite group', :js do ...@@ -150,6 +190,7 @@ RSpec.describe 'Project > Members > Invite group', :js do
end end
end end
end end
end
describe 'the groups dropdown' do describe 'the groups dropdown' do
context 'with multiple groups to choose from' do context 'with multiple groups to choose from' do
......
...@@ -4,7 +4,6 @@ require 'spec_helper' ...@@ -4,7 +4,6 @@ require 'spec_helper'
RSpec.describe 'Project members list' do RSpec.describe 'Project members list' do
include Select2Helper include Select2Helper
include Spec::Support::Helpers::Features::ListRowsHelpers
let(:user1) { create(:user, name: 'John Doe') } let(:user1) { create(:user, name: 'John Doe') }
let(:user2) { create(:user, name: 'Mary Jane') } let(:user2) { create(:user, name: 'Mary Jane') }
...@@ -13,16 +12,118 @@ RSpec.describe 'Project members list' do ...@@ -13,16 +12,118 @@ RSpec.describe 'Project members list' do
before do before do
stub_feature_flags(invite_members_group_modal: false) stub_feature_flags(invite_members_group_modal: false)
stub_feature_flags(vue_project_members_list: false)
sign_in(user1) sign_in(user1)
group.add_owner(user1) group.add_owner(user1)
end end
context 'when `vue_project_members_list` feature flag is enabled', :js do
include Spec::Support::Helpers::Features::MembersHelpers
it 'pushes `vue_project_members_list` feature flag to the frontend' do it 'pushes `vue_project_members_list` feature flag to the frontend' do
visit_members_page visit_members_page
expect(page).to have_pushed_frontend_feature_flags(vueProjectMembersList: false) expect(page).to have_pushed_frontend_feature_flags(vueProjectMembersList: true)
end
it 'show members from project and group' do
project.add_developer(user2)
visit_members_page
expect(first_row).to have_content(user1.name)
expect(second_row).to have_content(user2.name)
end
it 'show user once if member of both group and project' do
project.add_developer(user1)
visit_members_page
expect(first_row).to have_content(user1.name)
expect(second_row).to be_blank
end
it 'update user access level', :js do
project.add_developer(user2)
visit_members_page
page.within find_member_row(user2) do
click_button('Developer')
click_button('Reporter')
expect(page).to have_button('Reporter')
end
end
it 'add user to project', :js do
visit_members_page
add_user(user2.id, 'Reporter')
page.within find_member_row(user2) do
expect(page).to have_button('Reporter')
end
end
it 'remove user from project', :js do
other_user = create(:user)
project.add_developer(other_user)
visit_members_page
# Open modal
page.within find_member_row(other_user) do
click_button 'Remove member'
end
page.within('[role="dialog"]') do
expect(page).to have_unchecked_field 'Also unassign this user from related issues and merge requests'
click_button('Remove member')
end
wait_for_requests
expect(members_table).not_to have_content(other_user.name)
end
it 'invite user to project', :js do
visit_members_page
add_user('test@example.com', 'Reporter')
click_link 'Invited'
page.within find_invited_member_row('test@example.com') do
expect(page).to have_button('Reporter')
end
end
context 'project bots' do
let(:project_bot) { create(:user, :project_bot, name: 'project_bot') }
before do
project.add_maintainer(project_bot)
end
it 'does not show form used to change roles and "Expiration date" or the remove user button' do
visit_members_page
page.within find_member_row(project_bot) do
expect(page).not_to have_button('Maintainer')
expect(page).to have_field('Expiration date', disabled: true)
expect(page).not_to have_button('Remove member')
end
end
end
end
context 'when `vue_project_members_list` feature flag is disabled' do
include Spec::Support::Helpers::Features::ListRowsHelpers
before do
stub_feature_flags(vue_project_members_list: false)
end end
it 'show members from project and group' do it 'show members from project and group' do
...@@ -116,6 +217,9 @@ RSpec.describe 'Project members list' do ...@@ -116,6 +217,9 @@ RSpec.describe 'Project members list' do
expect(page).to have_no_selector("#project_member_#{project_member.id} .btn-danger") expect(page).to have_no_selector("#project_member_#{project_member.id} .btn-danger")
end end
end end
end
private
def add_user(id, role) def add_user(id, role)
page.within ".invite-users-form" do page.within ".invite-users-form" do
......
...@@ -5,20 +5,74 @@ require 'spec_helper' ...@@ -5,20 +5,74 @@ require 'spec_helper'
RSpec.describe 'Projects > Members > Maintainer adds member with expiration date', :js do RSpec.describe 'Projects > Members > Maintainer adds member with expiration date', :js do
include Select2Helper include Select2Helper
include ActiveSupport::Testing::TimeHelpers include ActiveSupport::Testing::TimeHelpers
include Spec::Support::Helpers::Features::MembersHelpers
let_it_be(:maintainer) { create(:user) } let_it_be(:maintainer) { create(:user) }
let_it_be(:project) { create(:project) } let_it_be(:project) { create(:project) }
let(:new_member) { create(:user) } let(:new_member) { create(:user) }
before do before do
stub_feature_flags(vue_project_members_list: false)
travel_to Time.now.utc.beginning_of_day travel_to Time.now.utc.beginning_of_day
project.add_maintainer(maintainer) project.add_maintainer(maintainer)
sign_in(maintainer) sign_in(maintainer)
end end
context 'when `vue_project_members_list` feature flag is enabled' do
it 'expiration date is displayed in the members list' do
stub_feature_flags(invite_members_group_modal: false)
visit project_project_members_path(project)
page.within '.invite-users-form' do
select2(new_member.id, from: '#user_ids', multiple: true)
fill_in 'expires_at', with: 5.days.from_now.to_date
find_field('expires_at').native.send_keys :enter
click_on 'Invite'
end
page.within find_member_row(new_member) do
expect(page).to have_content(/in \d days/)
end
end
it 'changes expiration date' do
project.team.add_users([new_member.id], :developer, expires_at: 3.days.from_now.to_date)
visit project_project_members_path(project)
page.within find_member_row(new_member) do
fill_in 'Expiration date', with: 5.days.from_now.to_date
find_field('Expiration date').native.send_keys :enter
wait_for_requests
expect(page).to have_content(/in \d days/)
end
end
it 'clears expiration date' do
project.team.add_users([new_member.id], :developer, expires_at: 5.days.from_now.to_date)
visit project_project_members_path(project)
page.within find_member_row(new_member) do
expect(page).to have_content(/in \d days/)
find('[data-testid="clear-button"]').click
wait_for_requests
expect(page).to have_content('No expiration set')
end
end
end
context 'when `vue_project_members_list` feature flag is disabled' do
before do
stub_feature_flags(vue_project_members_list: false)
end
it 'expiration date is displayed in the members list' do it 'expiration date is displayed in the members list' do
stub_feature_flags(invite_members_group_modal: false) stub_feature_flags(invite_members_group_modal: false)
...@@ -39,7 +93,7 @@ RSpec.describe 'Projects > Members > Maintainer adds member with expiration date ...@@ -39,7 +93,7 @@ RSpec.describe 'Projects > Members > Maintainer adds member with expiration date
end end
it 'changes expiration date' do it 'changes expiration date' do
project.team.add_users([new_member.id], :developer, expires_at: Date.today.to_date) project.team.add_users([new_member.id], :developer, expires_at: 1.day.from_now.to_date)
visit project_project_members_path(project) visit project_project_members_path(project)
page.within "#project_member_#{project_member_id}" do page.within "#project_member_#{project_member_id}" do
...@@ -66,6 +120,7 @@ RSpec.describe 'Projects > Members > Maintainer adds member with expiration date ...@@ -66,6 +120,7 @@ RSpec.describe 'Projects > Members > Maintainer adds member with expiration date
expect(page).not_to have_content('Expires in') expect(page).not_to have_content('Expires in')
end end
end end
end
def project_member_id def project_member_id
project.members.find_by(user_id: new_member).id project.members.find_by(user_id: new_member).id
......
...@@ -3,18 +3,106 @@ ...@@ -3,18 +3,106 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe 'Projects > Members > Sorting' do RSpec.describe 'Projects > Members > Sorting' do
include Spec::Support::Helpers::Features::MembersHelpers
let(:maintainer) { create(:user, name: 'John Doe') } let(:maintainer) { create(:user, name: 'John Doe') }
let(:developer) { create(:user, name: 'Mary Jane', last_sign_in_at: 5.days.ago) } let(:developer) { create(:user, name: 'Mary Jane', last_sign_in_at: 5.days.ago) }
let(:project) { create(:project, namespace: maintainer.namespace, creator: maintainer) } let(:project) { create(:project, namespace: maintainer.namespace, creator: maintainer) }
before do before do
stub_feature_flags(vue_project_members_list: false)
create(:project_member, :developer, user: developer, project: project, created_at: 3.days.ago) create(:project_member, :developer, user: developer, project: project, created_at: 3.days.ago)
sign_in(maintainer) sign_in(maintainer)
end end
context 'when `vue_project_members_list` feature flag is enabled', :js do
it 'sorts by account by default' do
visit_members_list(sort: nil)
expect(first_row).to have_content(maintainer.name)
expect(second_row).to have_content(developer.name)
expect_sort_by('Account', :asc)
end
it 'sorts by max role ascending' do
visit_members_list(sort: :access_level_asc)
expect(first_row).to have_content(developer.name)
expect(second_row).to have_content(maintainer.name)
expect_sort_by('Max role', :asc)
end
it 'sorts by max role descending' do
visit_members_list(sort: :access_level_desc)
expect(first_row).to have_content(maintainer.name)
expect(second_row).to have_content(developer.name)
expect_sort_by('Max role', :desc)
end
it 'sorts by access granted ascending' do
visit_members_list(sort: :last_joined)
expect(first_row).to have_content(maintainer.name)
expect(second_row).to have_content(developer.name)
expect_sort_by('Access granted', :asc)
end
it 'sorts by access granted descending' do
visit_members_list(sort: :oldest_joined)
expect(first_row).to have_content(developer.name)
expect(second_row).to have_content(maintainer.name)
expect_sort_by('Access granted', :desc)
end
it 'sorts by account ascending' do
visit_members_list(sort: :name_asc)
expect(first_row).to have_content(maintainer.name)
expect(second_row).to have_content(developer.name)
expect_sort_by('Account', :asc)
end
it 'sorts by account descending' do
visit_members_list(sort: :name_desc)
expect(first_row).to have_content(developer.name)
expect(second_row).to have_content(maintainer.name)
expect_sort_by('Account', :desc)
end
it 'sorts by last sign-in ascending', :clean_gitlab_redis_shared_state do
visit_members_list(sort: :recent_sign_in)
expect(first_row).to have_content(maintainer.name)
expect(second_row).to have_content(developer.name)
expect_sort_by('Last sign-in', :asc)
end
it 'sorts by last sign-in descending', :clean_gitlab_redis_shared_state do
visit_members_list(sort: :oldest_sign_in)
expect(first_row).to have_content(developer.name)
expect(second_row).to have_content(maintainer.name)
expect_sort_by('Last sign-in', :desc)
end
end
context 'when `vue_project_members_list` feature flag is disabled' do
before do
stub_feature_flags(vue_project_members_list: false)
end
it 'sorts alphabetically by default' do it 'sorts alphabetically by default' do
visit_members_list(sort: nil) visit_members_list(sort: nil)
...@@ -86,6 +174,9 @@ RSpec.describe 'Projects > Members > Sorting' do ...@@ -86,6 +174,9 @@ RSpec.describe 'Projects > Members > Sorting' do
expect(second_member).to include(maintainer.name) expect(second_member).to include(maintainer.name)
expect(page).to have_css('.qa-user-sort-dropdown .dropdown-toggle-text', text: 'Oldest sign in') expect(page).to have_css('.qa-user-sort-dropdown .dropdown-toggle-text', text: 'Oldest sign in')
end end
end
private
def visit_members_list(sort:) def visit_members_list(sort:)
visit project_project_members_path(project, sort: sort) visit project_project_members_path(project, sort: sort)
...@@ -98,4 +189,11 @@ RSpec.describe 'Projects > Members > Sorting' do ...@@ -98,4 +189,11 @@ RSpec.describe 'Projects > Members > Sorting' do
def second_member def second_member
page.all('ul.content-list > li').last.text page.all('ul.content-list > li').last.text
end end
def expect_sort_by(text, sort_direction)
within('[data-testid="members-sort-dropdown"]') do
expect(page).to have_css('button[aria-haspopup="true"]', text: text)
expect(page).to have_button("Sorting Direction: #{sort_direction == :asc ? 'Ascending' : 'Descending'}")
end
end
end end
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe 'Projects > Members > Tabs' do RSpec.describe 'Projects > Members > Tabs' do
include Spec::Support::Helpers::Features::MembersHelpers
using RSpec::Parameterized::TableSyntax using RSpec::Parameterized::TableSyntax
let_it_be(:user) { create(:user) } let_it_be(:user) { create(:user) }
...@@ -19,10 +20,8 @@ RSpec.describe 'Projects > Members > Tabs' do ...@@ -19,10 +20,8 @@ RSpec.describe 'Projects > Members > Tabs' do
end end
end end
context 'tabs' do
before do before do
stub_feature_flags(vue_project_members_list: false)
allow(Kaminari.config).to receive(:default_per_page).and_return(1)
sign_in(user) sign_in(user)
visit project_project_members_path(project) visit project_project_members_path(project)
end end
...@@ -43,6 +42,44 @@ RSpec.describe 'Projects > Members > Tabs' do ...@@ -43,6 +42,44 @@ RSpec.describe 'Projects > Members > Tabs' do
context 'displays "Members" tab by default' do context 'displays "Members" tab by default' do
it_behaves_like 'active "Members" tab' it_behaves_like 'active "Members" tab'
end end
end
context 'when `vue_project_members_list` feature flag is enabled' do
before do
sign_in(user)
visit project_project_members_path(project)
end
context 'when searching "Groups"', :js do
before do
click_link 'Groups'
fill_in_filtered_search 'Search groups', with: 'group'
end
it 'displays "Groups" tab' do
expect(page).to have_selector('.nav-link.active', text: 'Groups')
end
context 'and then searching "Members"' do
before do
click_link 'Members 3'
fill_in_filtered_search 'Filter members', with: 'user'
end
it_behaves_like 'active "Members" tab'
end
end
end
context 'when `vue_project_members_list` feature flag is disabled' do
before do
stub_feature_flags(vue_project_members_list: false)
sign_in(user)
visit project_project_members_path(project)
end
context 'when searching "Groups"', :js do context 'when searching "Groups"', :js do
before do before do
...@@ -71,4 +108,5 @@ RSpec.describe 'Projects > Members > Tabs' do ...@@ -71,4 +108,5 @@ RSpec.describe 'Projects > Members > Tabs' do
it_behaves_like 'active "Members" tab' it_behaves_like 'active "Members" tab'
end end
end end
end
end end
...@@ -3,6 +3,9 @@ ...@@ -3,6 +3,9 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe 'Projects > Settings > User manages project members' do RSpec.describe 'Projects > Settings > User manages project members' do
include Spec::Support::Helpers::Features::MembersHelpers
include Select2Helper
let(:group) { create(:group, name: 'OpenSource') } let(:group) { create(:group, name: 'OpenSource') }
let(:project) { create(:project) } let(:project) { create(:project) }
let(:project2) { create(:project) } let(:project2) { create(:project) }
...@@ -11,13 +14,69 @@ RSpec.describe 'Projects > Settings > User manages project members' do ...@@ -11,13 +14,69 @@ RSpec.describe 'Projects > Settings > User manages project members' do
let(:user_mike) { create(:user, name: 'Mike') } let(:user_mike) { create(:user, name: 'Mike') }
before do before do
stub_feature_flags(vue_project_members_list: false)
project.add_maintainer(user) project.add_maintainer(user)
project.add_developer(user_dmitriy) project.add_developer(user_dmitriy)
sign_in(user) sign_in(user)
end end
context 'when `vue_project_members_list` feature flag is enabled' do
it 'cancels a team member', :js do
visit(project_project_members_path(project))
page.within find_member_row(user_dmitriy) do
click_button 'Remove member'
end
page.within('[role="dialog"]') do
expect(page).to have_unchecked_field 'Also unassign this user from related issues and merge requests'
click_button('Remove member')
end
visit(project_project_members_path(project))
expect(members_table).not_to have_content(user_dmitriy.name)
expect(members_table).not_to have_content(user_dmitriy.username)
end
it 'imports a team from another project', :js do
stub_feature_flags(invite_members_group_modal: false)
project2.add_maintainer(user)
project2.add_reporter(user_mike)
visit(project_project_members_path(project))
page.within('.invite-users-form') do
click_link('Import')
end
select2(project2.id, from: '#source_project_id')
click_button('Import project members')
expect(find_member_row(user_mike)).to have_content('Reporter')
end
it 'shows all members of project shared group', :js do
group.add_owner(user)
group.add_developer(user_dmitriy)
share_link = project.project_group_links.new(group_access: Gitlab::Access::MAINTAINER)
share_link.group_id = group.id
share_link.save!
visit(project_project_members_path(project))
click_link 'Groups'
expect(find_group_row(group)).to have_content('Maintainer')
end
end
context 'when `vue_project_members_list` feature flag is disabled' do
before do
stub_feature_flags(vue_project_members_list: false)
end
it 'cancels a team member', :js do it 'cancels a team member', :js do
visit(project_project_members_path(project)) visit(project_project_members_path(project))
...@@ -78,4 +137,5 @@ RSpec.describe 'Projects > Settings > User manages project members' do ...@@ -78,4 +137,5 @@ RSpec.describe 'Projects > Settings > User manages project members' do
expect(first('.group_member')).to have_content('Maintainer') expect(first('.group_member')).to have_content('Maintainer')
end end
end end
end
end end
...@@ -30,6 +30,32 @@ module Spec ...@@ -30,6 +30,32 @@ module Spec
def invite_users_form def invite_users_form
page.find('[data-testid="invite-users-form"]') page.find('[data-testid="invite-users-form"]')
end end
def find_row(name)
page.within(members_table) do
page.find('tbody > tr', text: name)
end
end
def find_member_row(user)
find_row(user.name)
end
def find_invited_member_row(email)
find_row(email)
end
def find_group_row(group)
find_row(group.full_name)
end
def fill_in_filtered_search(label, with:)
page.within '[data-testid="members-filtered-search-bar"]' do
find_field(label).click
find('input').native.send_keys(with)
click_button 'Search'
end
end
end 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