Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2020-11-02 06:08:53 +00:00
parent 9a34a91714
commit 26c50e0eb9
29 changed files with 381 additions and 151 deletions

View file

@ -48,6 +48,7 @@ export default {
<div>
<gl-table
class="members-table"
data-testid="members-table"
head-variant="white"
stacked="lg"
:fields="filteredFields"

View file

@ -8,7 +8,6 @@ class ApplicationSetting < ApplicationRecord
include IgnorableColumns
ignore_column :namespace_storage_size_limit, remove_with: '13.5', remove_after: '2020-09-22'
ignore_column :instance_statistics_visibility_private, remove_with: '13.6', remove_after: '2020-10-22'
INSTANCE_REVIEW_MIN_USERS = 50
GRAFANA_URL_ERROR_MESSAGE = 'Please check your Grafana URL setting in ' \

View file

@ -14,6 +14,8 @@ class AlertsService < Service
before_validation :prevent_token_assignment
before_validation :ensure_token, if: :activated?
after_save :update_http_integration
def url
return if instance? || template?
@ -77,6 +79,14 @@ class AlertsService < Service
def url_helpers
Gitlab::Routing.url_helpers
end
def update_http_integration
return unless project_id && type == 'AlertsService'
AlertManagement::SyncAlertServiceDataService # rubocop: disable CodeReuse/ServiceClass
.new(self)
.execute
end
end
AlertsService.prepend_if_ee('EE::AlertsService')

View file

@ -0,0 +1,56 @@
# frozen_string_literal: true
module AlertManagement
class SyncAlertServiceDataService
# @param alert_service [AlertsService]
def initialize(alert_service)
@alert_service = alert_service
end
def execute
http_integration = find_http_integration
result = if http_integration
update_integration_data(http_integration)
else
create_integration
end
result ? ServiceResponse.success : ServiceResponse.error(message: 'Update failed')
end
private
attr_reader :alert_service
def find_http_integration
AlertManagement::HttpIntegrationsFinder.new(
alert_service.project,
endpoint_identifier: ::AlertManagement::HttpIntegration::LEGACY_IDENTIFIER
)
.execute
.first
end
def create_integration
new_integration = AlertManagement::HttpIntegration.create(
project_id: alert_service.project_id,
name: 'HTTP endpoint',
endpoint_identifier: AlertManagement::HttpIntegration::LEGACY_IDENTIFIER,
active: alert_service.active,
encrypted_token: alert_service.data.encrypted_token,
encrypted_token_iv: alert_service.data.encrypted_token_iv
)
new_integration.persisted?
end
def update_integration_data(http_integration)
http_integration.update(
active: alert_service.active,
encrypted_token: alert_service.data.encrypted_token,
encrypted_token_iv: alert_service.data.encrypted_token_iv
)
end
end
end

View file

@ -16,7 +16,7 @@
= sprite_icon('search', css_class: 'gl-vertical-align-middle!')
= label_tag :sort_by, _('Sort by'), class: 'col-form-label label-bold px-2'
= render 'shared/members/sort_dropdown'
%ul.content-list.members-list{ data: { qa_selector: 'members_list' } }
%ul.content-list.members-list{ data: { qa_selector: 'members_list', testid: 'members-table' } }
= render partial: 'shared/members/member',
collection: members, as: :member,
locals: { membership_source: project,

View file

@ -1,7 +1,7 @@
- filter = params[:two_factor] || 'everyone'
- filter_options = { 'everyone' => _('Everyone'), 'enabled' => _('Enabled'), 'disabled' => _('Disabled') }
.dropdown.inline.member-filter-2fa-dropdown
= dropdown_toggle(filter_options[filter], { toggle: 'dropdown' })
.dropdown.inline.member-filter-2fa-dropdown{ data: { testid: 'member-filter-2fa-dropdown' } }
= dropdown_toggle(filter_options[filter], { toggle: 'dropdown', testid: 'dropdown-toggle' })
%ul.dropdown-menu.dropdown-menu-align-right.dropdown-menu-selectable
%li.dropdown-header
= _("Filter by two-factor authentication")

View file

@ -5,7 +5,7 @@
- import_path = local_assigns[:import_path]
.row
.col-sm-12
= form_tag submit_url, class: 'invite-users-form', method: :post do
= form_tag submit_url, class: 'invite-users-form', data: { testid: 'invite-users-form' }, method: :post do
.form-group
= label_tag :user_ids, _("GitLab member or Email address"), class: "label-bold"
= users_select_tag(:user_ids, multiple: true, class: 'input-clamp qa-member-select-field', scope: :all, email_user: true, placeholder: 'Search for members to update or invite')

View file

@ -2,5 +2,5 @@
.search-control-wrap.gl-relative
= search_field_tag name, params[name], { placeholder: _('Search'), class: 'form-control', spellcheck: false }
%button.user-search-btn.border-left.gl-display-flex.gl-align-items-center.gl-justify-content-center{ type: 'submit', 'aria': { label: _('Submit search') } }
%button.user-search-btn.border-left.gl-display-flex.gl-align-items-center.gl-justify-content-center{ type: 'submit', 'aria': { label: _('Submit search') }, data: { testid: 'user-search-submit' } }
= sprite_icon('search')

View file

@ -1,5 +1,5 @@
.dropdown.inline.qa-user-sort-dropdown
= dropdown_toggle(member_sort_options_hash[@sort], { toggle: 'dropdown' })
.dropdown.inline.qa-user-sort-dropdown{ data: { testid: 'user-sort-dropdown' } }
= dropdown_toggle(member_sort_options_hash[@sort], { toggle: 'dropdown', testid: 'dropdown-toggle' })
%ul.dropdown-menu.dropdown-menu-right.dropdown-menu-selectable
%li.dropdown-header
= _("Sort by")
@ -8,12 +8,12 @@
= link_to filter_group_project_member_path(sort: value), class: ("is-active" if @sort == value) do
= title
%li.divider
%li{ data: { 'qa-selector': 'filter-members-with-inherited-permissions' } }
%li{ data: { testid: 'filter-members-with-inherited-permissions' } }
= link_to filter_group_project_member_path(with_inherited_permissions: nil), class: ("is-active" unless params[:with_inherited_permissions].present?) do
= _("Show all members")
%li{ data: { 'qa-selector': 'filter-members-with-inherited-permissions' } }
%li{ data: { testid: 'filter-members-with-inherited-permissions' } }
= link_to filter_group_project_member_path(with_inherited_permissions: 'exclude'), class: ("is-active" if params[:with_inherited_permissions] == 'exclude') do
= _("Show only direct members")
%li{ data: { 'qa-selector': 'filter-members-with-inherited-permissions' } }
%li{ data: { testid: 'filter-members-with-inherited-permissions' } }
= link_to filter_group_project_member_path(with_inherited_permissions: 'only'), class: ("is-active" if params[:with_inherited_permissions] == 'only') do
= _("Show only inherited members")

View file

@ -0,0 +1,5 @@
---
title: Migrate Alert Service to HTTP Integrations model
merge_request: 46188
author:
type: added

View file

@ -0,0 +1,51 @@
# frozen_string_literal: true
class MigrateServicesToHttpIntegrations < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
ALERT_SERVICE_TYPE = 'AlertsService'
SERVICE_NAMES_IDENTIFIER = {
name: 'HTTP endpoint',
identifier: 'legacy'
}
class HttpIntegration < ActiveRecord::Base
self.table_name = 'alert_management_http_integrations'
end
# For each Alerts service,
# Create the matching HttpIntegration
def up
HttpIntegration.reset_column_information
sql = <<~SQL
SELECT * FROM services
JOIN alerts_service_data
ON (services.id = alerts_service_data.service_id)
WHERE type = '#{ALERT_SERVICE_TYPE}'
AND active = TRUE
SQL
current_time = Time.current
values = select_all(sql).map do |alerts_service|
{
project_id: alerts_service['project_id'],
name: SERVICE_NAMES_IDENTIFIER[:name],
endpoint_identifier: SERVICE_NAMES_IDENTIFIER[:identifier],
encrypted_token: alerts_service['encrypted_token'],
encrypted_token_iv: alerts_service['encrypted_token_iv'],
active: alerts_service['active'],
updated_at: current_time,
created_at: current_time
}
end
HttpIntegration.insert_all(values) if values.present?
end
def down
# no-op
end
end

View file

@ -0,0 +1 @@
34e357b739235d627e543e1bc7202e0cf26f5b1ca8021bb25357e29e883f785b

View file

@ -19,7 +19,7 @@ module QA
end
end
it 'closes an issue', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/225303', type: :bug }, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/852' do
it 'closes an issue', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/225303', type: :bug }, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1085' do
closed_issue.visit!
Page::Project::Issue::Show.perform do |issue_page|

View file

@ -0,0 +1,8 @@
# frozen_string_literal: true
FactoryBot.define do
factory :alerts_service_data do
service { association(:alerts_service) }
token { SecureRandom.hex }
end
end

View file

@ -56,6 +56,10 @@ FactoryBot.define do
trait :inactive do
active { false }
end
before(:create) do |service|
service.data = build(:alerts_service_data, service: service)
end
end
factory :drone_ci_service do

View file

@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe 'Admin Groups' do
include Select2Helper
include Spec::Support::Helpers::Features::MembersHelpers
let(:internal) { Gitlab::VisibilityLevel::INTERNAL }
let(:user) { create :user }
@ -11,8 +12,6 @@ RSpec.describe 'Admin Groups' do
let!(:current_user) { create(:admin) }
before do
stub_feature_flags(vue_group_members_list: false)
sign_in(current_user)
stub_application_setting(default_group_visibility: internal)
end
@ -176,7 +175,7 @@ RSpec.describe 'Admin Groups' do
click_button 'Invite'
page.within '[data-qa-selector="members_list"]' do
page.within members_table do
expect(page).to have_content(current_user.name)
expect(page).to have_content('Developer')
end

View file

@ -2,16 +2,19 @@
require 'spec_helper'
RSpec.describe 'Groups > Members > Filter members' do
RSpec.describe 'Groups > Members > Filter members', :js do
include Spec::Support::Helpers::Features::MembersHelpers
let(:user) { create(:user) }
let(:nested_group_user) { create(:user) }
let(:user_with_2fa) { create(:user, :two_factor_via_otp) }
let(:group) { create(:group) }
let(:nested_group) { create(:group, parent: group) }
before do
stub_feature_flags(vue_group_members_list: false)
two_factor_auth_dropdown_toggle_selector = '[data-testid="member-filter-2fa-dropdown"] [data-testid="dropdown-toggle"]'
active_inherited_members_filter_selector = '[data-testid="filter-members-with-inherited-permissions"] a.is-active'
before do
group.add_owner(user)
group.add_maintainer(user_with_2fa)
nested_group.add_maintainer(nested_group_user)
@ -24,23 +27,23 @@ RSpec.describe 'Groups > Members > Filter members' do
expect(member(0)).to include(user.name)
expect(member(1)).to include(user_with_2fa.name)
expect(page).to have_css('.member-filter-2fa-dropdown .dropdown-toggle-text', text: 'Everyone')
expect(page).to have_css(two_factor_auth_dropdown_toggle_selector, text: 'Everyone')
end
it 'shows only 2FA members' do
visit_members_list(group, two_factor: 'enabled')
expect(member(0)).to include(user_with_2fa.name)
expect(members_list.size).to eq(1)
expect(page).to have_css('.member-filter-2fa-dropdown .dropdown-toggle-text', text: 'Enabled')
expect(all_rows.size).to eq(1)
expect(page).to have_css(two_factor_auth_dropdown_toggle_selector, text: 'Enabled')
end
it 'shows only non 2FA members' do
visit_members_list(group, two_factor: 'disabled')
expect(member(0)).to include(user.name)
expect(members_list.size).to eq(1)
expect(page).to have_css('.member-filter-2fa-dropdown .dropdown-toggle-text', text: 'Disabled')
expect(all_rows.size).to eq(1)
expect(page).to have_css(two_factor_auth_dropdown_toggle_selector, text: 'Disabled')
end
it 'shows inherited members by default' do
@ -49,35 +52,31 @@ RSpec.describe 'Groups > Members > Filter members' do
expect(member(0)).to include(user.name)
expect(member(1)).to include(user_with_2fa.name)
expect(member(2)).to include(nested_group_user.name)
expect(members_list.size).to eq(3)
expect(all_rows.size).to eq(3)
expect(page).to have_css('[data-qa-selector="filter-members-with-inherited-permissions"] a.is-active', text: 'Show all members')
expect(page).to have_css(active_inherited_members_filter_selector, text: 'Show all members', visible: false)
end
it 'shows only group members' do
visit_members_list(nested_group, with_inherited_permissions: 'exclude')
expect(member(0)).to include(nested_group_user.name)
expect(members_list.size).to eq(1)
expect(page).to have_css('[data-qa-selector="filter-members-with-inherited-permissions"] a.is-active', text: 'Show only direct members')
expect(all_rows.size).to eq(1)
expect(page).to have_css(active_inherited_members_filter_selector, text: 'Show only direct members', visible: false)
end
it 'shows only inherited members' do
visit_members_list(nested_group, with_inherited_permissions: 'only')
expect(member(0)).to include(user.name)
expect(member(1)).to include(user_with_2fa.name)
expect(members_list.size).to eq(2)
expect(page).to have_css('[data-qa-selector="filter-members-with-inherited-permissions"] a.is-active', text: 'Show only inherited members')
expect(all_rows.size).to eq(2)
expect(page).to have_css(active_inherited_members_filter_selector, text: 'Show only inherited members', visible: false)
end
def visit_members_list(group, options = {})
visit group_group_members_path(group.to_param, options)
end
def members_list
page.all('ul.content-list > li')
end
def member(number)
members_list[number].text
all_rows[number].text
end
end

View file

@ -3,14 +3,14 @@
require 'spec_helper'
RSpec.describe 'Groups > Members > Leave group' do
include Spec::Support::Helpers::Features::MembersHelpers
let(:user) { create(:user) }
let(:other_user) { create(:user) }
let(:group) { create(:group) }
before do
stub_feature_flags(vue_group_members_list: false)
gitlab_sign_in(user)
sign_in(user)
end
it 'guest leaves the group' do
@ -61,7 +61,7 @@ RSpec.describe 'Groups > Members > Leave group' do
expect(group.users).not_to include(user)
end
it 'owner can not leave the group if they are the last owner' do
it 'owner can not leave the group if they are the last owner', :js do
group.add_owner(user)
visit group_path(group)
@ -70,7 +70,7 @@ RSpec.describe 'Groups > Members > Leave group' do
visit group_group_members_path(group)
expect(find(:css, '.project-members-page li', text: user.name)).to have_no_selector(:css, 'a.btn-danger')
expect(members_table).not_to have_selector 'button[title="Leave"]'
end
it 'owner can not leave the group by url param if they are the last owner', :js do

View file

@ -2,9 +2,8 @@
require 'spec_helper'
RSpec.describe 'Groups > Members > List members' do
include Select2Helper
include Spec::Support::Helpers::Features::ListRowsHelpers
RSpec.describe 'Groups > Members > List members', :js do
include Spec::Support::Helpers::Features::MembersHelpers
let(:user1) { create(:user, name: 'John Doe') }
let(:user2) { create(:user, name: 'Mary Jane') }
@ -12,8 +11,6 @@ RSpec.describe 'Groups > Members > List members' do
let(:nested_group) { create(:group, parent: group) }
before do
stub_feature_flags(vue_group_members_list: false)
sign_in(user1)
end
@ -42,10 +39,12 @@ RSpec.describe 'Groups > Members > List members' do
group.add_developer(user2)
end
subject { visit group_group_members_path(group) }
it 'shows the status' do
create(:user_status, user: user2, emoji: 'smirk', message: 'Authoring this object')
it_behaves_like 'showing user status' do
let(:user_with_status) { user2 }
visit group_group_members_path(nested_group)
expect(first_row).to have_selector('gl-emoji[data-name="smirk"]')
end
end
end

View file

@ -4,13 +4,11 @@ require 'spec_helper'
RSpec.describe 'Groups > Members > Manage groups', :js do
include Select2Helper
include Spec::Support::Helpers::Features::ListRowsHelpers
include Spec::Support::Helpers::Features::MembersHelpers
let_it_be(:user) { create(:user) }
before do
stub_feature_flags(vue_group_members_list: false)
sign_in(user)
end
@ -51,7 +49,6 @@ RSpec.describe 'Groups > Members > Manage groups', :js do
end
before do
travel_to Time.now.utc.beginning_of_day
group_link.update!(additional_link_attrs)
shared_group.add_owner(user)
@ -63,8 +60,12 @@ RSpec.describe 'Groups > Members > Manage groups', :js do
expect(page).to have_content(shared_with_group.name)
accept_confirm do
find(:css, '#tab-groups li', text: shared_with_group.name).find(:css, 'a.btn-danger').click
page.within(first_row) do
click_button 'Remove group'
end
page.within('[role="dialog"]') do
click_button('Remove group')
end
expect(page).not_to have_content(shared_with_group.name)
@ -75,7 +76,7 @@ RSpec.describe 'Groups > Members > Manage groups', :js do
page.within(first_row) do
click_button('Developer')
click_link('Maintainer')
click_button('Maintainer')
wait_for_requests
@ -86,33 +87,30 @@ RSpec.describe 'Groups > Members > Manage groups', :js do
it 'updates expiry date' do
click_groups_tab
expires_at_field = "member_expires_at_#{shared_with_group.id}"
fill_in "member_expires_at_#{shared_with_group.id}", with: 3.days.from_now.to_date
page.within first_row do
fill_in 'Expiration date', with: 5.days.from_now.to_date
find_field('Expiration date').native.send_keys :enter
find_field(expires_at_field).native.send_keys :enter
wait_for_requests
wait_for_requests
page.within(find('li.group_member')) do
expect(page).to have_content('Expires in 3 days')
expect(page).to have_content(/in \d days/)
end
end
context 'when expiry date is set' do
let(:additional_link_attrs) { { expires_at: 3.days.from_now.to_date } }
let(:additional_link_attrs) { { expires_at: 5.days.from_now.to_date } }
it 'clears expiry date' do
click_groups_tab
page.within(find('li.group_member')) do
expect(page).to have_content('Expires in 3 days')
page.within first_row do
expect(page).to have_content(/in \d days/)
page.within(find('.js-edit-member-form')) do
find('.js-clear-input').click
end
find('[data-testid="clear-button"]').click
wait_for_requests
expect(page).not_to have_content('Expires in')
expect(page).to have_content('No expiration set')
end
end
end
@ -128,6 +126,7 @@ RSpec.describe 'Groups > Members > Manage groups', :js do
end
def click_groups_tab
expect(page).to have_link 'Groups'
click_link "Groups"
end
end

View file

@ -4,15 +4,13 @@ require 'spec_helper'
RSpec.describe 'Groups > Members > Manage members' do
include Select2Helper
include Spec::Support::Helpers::Features::ListRowsHelpers
include Spec::Support::Helpers::Features::MembersHelpers
let(:user1) { create(:user, name: 'John Doe') }
let(:user2) { create(:user, name: 'Mary Jane') }
let(:group) { create(:group) }
before do
stub_feature_flags(vue_group_members_list: false)
sign_in(user1)
end
@ -24,7 +22,7 @@ RSpec.describe 'Groups > Members > Manage members' do
page.within(second_row) do
click_button('Developer')
click_link('Owner')
click_button('Owner')
expect(page).to have_button('Owner')
end
@ -71,11 +69,14 @@ RSpec.describe 'Groups > Members > Manage members' do
visit group_group_members_path(group)
# Open modal
find(:css, '.project-members-page li', text: user2.name).find(:css, 'button.btn-danger').click
page.within(second_row) do
click_button 'Remove member'
end
expect(page).to have_unchecked_field 'Also unassign this user from related issues and merge requests'
click_on('Remove member')
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
@ -103,16 +104,17 @@ RSpec.describe 'Groups > Members > Manage members' do
add_user('test@example.com', 'Reporter')
click_link('Invited')
expect(page).to have_link 'Invited'
click_link 'Invited'
page.within('.content-list.members-list') do
page.within(members_table) do
expect(page).to have_content('test@example.com')
expect(page).to have_content('Invited')
expect(page).to have_button('Reporter')
end
end
it 'guest can not manage other users' do
it 'guest can not manage other users', :js do
group.add_guest(user1)
group.add_developer(user2)
@ -126,7 +128,7 @@ RSpec.describe 'Groups > Members > Manage members' do
expect(page).not_to have_button 'Developer'
# Can not remove user2
expect(page).not_to have_css('a.btn-danger')
expect(page).not_to have_selector 'button[title="Remove member"]'
end
end

View file

@ -4,17 +4,13 @@ require 'spec_helper'
RSpec.describe 'Groups > Members > Owner adds member with expiration date', :js do
include Select2Helper
include ActiveSupport::Testing::TimeHelpers
include Spec::Support::Helpers::Features::MembersHelpers
let_it_be(:user1) { create(:user, name: 'John Doe') }
let_it_be(:group) { create(:group) }
let(:new_member) { create(:user, name: 'Mary Jane') }
before do
stub_feature_flags(vue_group_members_list: false)
travel_to Time.now.utc.beginning_of_day
group.add_owner(user1)
sign_in(user1)
end
@ -22,17 +18,17 @@ RSpec.describe 'Groups > Members > Owner adds member with expiration date', :js
it 'expiration date is displayed in the members list' do
visit group_group_members_path(group)
page.within '.invite-users-form' do
page.within invite_users_form do
select2(new_member.id, from: '#user_ids', multiple: true)
fill_in 'expires_at', with: 3.days.from_now.to_date
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 "#group_member_#{group_member_id}" do
expect(page).to have_content('Expires in 3 days')
page.within second_row do
expect(page).to have_content(/in \d days/)
end
end
@ -40,32 +36,28 @@ RSpec.describe 'Groups > Members > Owner adds member with expiration date', :js
group.add_developer(new_member)
visit group_group_members_path(group)
page.within "#group_member_#{group_member_id}" do
fill_in 'Expiration date', with: 3.days.from_now.to_date
page.within second_row 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('Expires in 3 days')
expect(page).to have_content(/in \d days/)
end
end
it 'clears expiration date' do
create(:group_member, :developer, user: new_member, group: group, expires_at: 3.days.from_now.to_date)
create(:group_member, :developer, user: new_member, group: group, expires_at: 5.days.from_now.to_date)
visit group_group_members_path(group)
page.within "#group_member_#{group_member_id}" do
expect(page).to have_content('Expires in 3 days')
page.within second_row do
expect(page).to have_content(/in \d days/)
find('.js-clear-input').click
find('[data-testid="clear-button"]').click
wait_for_requests
expect(page).not_to have_content('Expires in')
expect(page).to have_content('No expiration set')
end
end
def group_member_id
group.members.find_by(user_id: new_member).id
end
end

View file

@ -3,10 +3,6 @@
require 'spec_helper'
RSpec.describe 'Groups > Members > Maintainer manages access requests' do
before do
stub_feature_flags(vue_group_members_list: false)
end
it_behaves_like 'Maintainer manages access requests' do
let(:has_tabs) { true }
let(:entity) { create(:group, :public) }

View file

@ -2,7 +2,9 @@
require 'spec_helper'
RSpec.describe 'Search group member' do
RSpec.describe 'Search group member', :js do
include Spec::Support::Helpers::Features::MembersHelpers
let(:user) { create :user }
let(:member) { create :user }
@ -14,8 +16,6 @@ RSpec.describe 'Search group member' do
end
before do
stub_feature_flags(vue_group_members_list: false)
sign_in(user)
visit group_group_members_path(guest_group)
end
@ -23,11 +23,10 @@ RSpec.describe 'Search group member' do
it 'renders member users' do
page.within '[data-testid="user-search-form"]' do
fill_in 'search', with: member.name
find('.user-search-btn').click
find('[data-testid="user-search-submit"]').click
end
group_members_list = find('[data-qa-selector="members_list"]')
expect(group_members_list).to have_content(member.name)
expect(group_members_list).not_to have_content(user.name)
expect(members_table).to have_content(member.name)
expect(members_table).not_to have_content(user.name)
end
end

View file

@ -2,14 +2,16 @@
require 'spec_helper'
RSpec.describe 'Groups > Members > Sort members' do
RSpec.describe 'Groups > Members > Sort members', :js do
include Spec::Support::Helpers::Features::MembersHelpers
let(:owner) { create(:user, name: 'John Doe') }
let(:developer) { create(:user, name: 'Mary Jane', last_sign_in_at: 5.days.ago) }
let(:group) { create(:group) }
before do
stub_feature_flags(vue_group_members_list: false)
dropdown_toggle_selector = '[data-testid="user-sort-dropdown"] [data-testid="dropdown-toggle"]'
before do
create(:group_member, :owner, user: owner, group: group, created_at: 5.days.ago)
create(:group_member, :developer, user: developer, group: group, created_at: 3.days.ago)
@ -19,84 +21,76 @@ RSpec.describe 'Groups > Members > Sort members' do
it 'sorts alphabetically by default' do
visit_members_list(sort: nil)
expect(first_member).to include(owner.name)
expect(second_member).to include(developer.name)
expect(page).to have_css('.qa-user-sort-dropdown .dropdown-toggle-text', text: 'Name, ascending')
expect(first_row.text).to include(owner.name)
expect(second_row.text).to include(developer.name)
expect(page).to have_css(dropdown_toggle_selector, text: 'Name, ascending')
end
it 'sorts by access level ascending' do
visit_members_list(sort: :access_level_asc)
expect(first_member).to include(developer.name)
expect(second_member).to include(owner.name)
expect(page).to have_css('.qa-user-sort-dropdown .dropdown-toggle-text', text: 'Access level, ascending')
expect(first_row.text).to include(developer.name)
expect(second_row.text).to include(owner.name)
expect(page).to have_css(dropdown_toggle_selector, text: 'Access level, ascending')
end
it 'sorts by access level descending' do
visit_members_list(sort: :access_level_desc)
expect(first_member).to include(owner.name)
expect(second_member).to include(developer.name)
expect(page).to have_css('.qa-user-sort-dropdown .dropdown-toggle-text', text: 'Access level, descending')
expect(first_row.text).to include(owner.name)
expect(second_row.text).to include(developer.name)
expect(page).to have_css(dropdown_toggle_selector, text: 'Access level, descending')
end
it 'sorts by last joined' do
visit_members_list(sort: :last_joined)
expect(first_member).to include(developer.name)
expect(second_member).to include(owner.name)
expect(page).to have_css('.qa-user-sort-dropdown .dropdown-toggle-text', text: 'Last joined')
expect(first_row.text).to include(developer.name)
expect(second_row.text).to include(owner.name)
expect(page).to have_css(dropdown_toggle_selector, text: 'Last joined')
end
it 'sorts by oldest joined' do
visit_members_list(sort: :oldest_joined)
expect(first_member).to include(owner.name)
expect(second_member).to include(developer.name)
expect(page).to have_css('.qa-user-sort-dropdown .dropdown-toggle-text', text: 'Oldest joined')
expect(first_row.text).to include(owner.name)
expect(second_row.text).to include(developer.name)
expect(page).to have_css(dropdown_toggle_selector, text: 'Oldest joined')
end
it 'sorts by name ascending' do
visit_members_list(sort: :name_asc)
expect(first_member).to include(owner.name)
expect(second_member).to include(developer.name)
expect(page).to have_css('.qa-user-sort-dropdown .dropdown-toggle-text', text: 'Name, ascending')
expect(first_row.text).to include(owner.name)
expect(second_row.text).to include(developer.name)
expect(page).to have_css(dropdown_toggle_selector, text: 'Name, ascending')
end
it 'sorts by name descending' do
visit_members_list(sort: :name_desc)
expect(first_member).to include(developer.name)
expect(second_member).to include(owner.name)
expect(page).to have_css('.qa-user-sort-dropdown .dropdown-toggle-text', text: 'Name, descending')
expect(first_row.text).to include(developer.name)
expect(second_row.text).to include(owner.name)
expect(page).to have_css(dropdown_toggle_selector, text: 'Name, descending')
end
it 'sorts by recent sign in', :clean_gitlab_redis_shared_state do
visit_members_list(sort: :recent_sign_in)
expect(first_member).to include(owner.name)
expect(second_member).to include(developer.name)
expect(page).to have_css('.qa-user-sort-dropdown .dropdown-toggle-text', text: 'Recent sign in')
expect(first_row.text).to include(owner.name)
expect(second_row.text).to include(developer.name)
expect(page).to have_css(dropdown_toggle_selector, text: 'Recent sign in')
end
it 'sorts by oldest sign in', :clean_gitlab_redis_shared_state do
visit_members_list(sort: :oldest_sign_in)
expect(first_member).to include(developer.name)
expect(second_member).to include(owner.name)
expect(page).to have_css('.qa-user-sort-dropdown .dropdown-toggle-text', text: 'Oldest sign in')
expect(first_row.text).to include(developer.name)
expect(second_row.text).to include(owner.name)
expect(page).to have_css(dropdown_toggle_selector, text: 'Oldest sign in')
end
def visit_members_list(sort:)
visit group_group_members_path(group.to_param, sort: sort)
end
def first_member
page.all('ul.content-list > li').first.text
end
def second_member
page.all('ul.content-list > li').last.text
end
end

View file

@ -0,0 +1,26 @@
# frozen_string_literal: true
require 'spec_helper'
require Rails.root.join('db', 'migrate', '20201027002551_migrate_services_to_http_integrations.rb')
RSpec.describe MigrateServicesToHttpIntegrations do
let!(:namespace) { table(:namespaces).create!(name: 'namespace', path: 'namespace') }
let!(:project) { table(:projects).create!(id: 1, namespace_id: namespace.id) }
let!(:alert_service) { table(:services).create!(type: 'AlertsService', project_id: project.id, active: true) }
let!(:alert_service_data) { table(:alerts_service_data).create!(service_id: alert_service.id, encrypted_token: 'test', encrypted_token_iv: 'test')}
let(:http_integrations) { table(:alert_management_http_integrations) }
describe '#up' do
it 'creates the http integrations from the alert services', :aggregate_failures do
expect { migrate! }.to change { http_integrations.count }.by(1)
http_integration = http_integrations.last
expect(http_integration.project_id).to eq(alert_service.project_id)
expect(http_integration.encrypted_token).to eq(alert_service_data.encrypted_token)
expect(http_integration.encrypted_token_iv).to eq(alert_service_data.encrypted_token_iv)
expect(http_integration.active).to eq(alert_service.active)
expect(http_integration.name).to eq(described_class::SERVICE_NAMES_IDENTIFIER[:name])
expect(http_integration.endpoint_identifier).to eq(described_class::SERVICE_NAMES_IDENTIFIER[:identifier])
end
end
end

View file

@ -0,0 +1,55 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe AlertManagement::SyncAlertServiceDataService do
let_it_be(:alerts_service) do
AlertsService.skip_callback(:save, :after, :update_http_integration)
service = create(:alerts_service, :active)
AlertsService.set_callback(:save, :after, :update_http_integration)
service
end
describe '#execute' do
subject(:execute) { described_class.new(alerts_service).execute }
context 'without http integration' do
it 'creates the integration' do
expect { execute }
.to change { AlertManagement::HttpIntegration.count }.by(1)
end
it 'returns a success' do
expect(subject.success?).to eq(true)
end
end
context 'existing legacy http integration' do
let_it_be(:integration) { create(:alert_management_http_integration, :legacy, project: alerts_service.project) }
it 'updates the integration' do
expect { execute }
.to change { integration.reload.encrypted_token }.to(alerts_service.data.encrypted_token)
.and change { integration.encrypted_token_iv }.to(alerts_service.data.encrypted_token_iv)
end
it 'returns a success' do
expect(subject.success?).to eq(true)
end
end
context 'existing other http integration' do
let_it_be(:integration) { create(:alert_management_http_integration, project: alerts_service.project) }
it 'creates the integration' do
expect { execute }
.to change { AlertManagement::HttpIntegration.count }.by(1)
end
it 'returns a success' do
expect(subject.success?).to eq(true)
end
end
end
end

View file

@ -0,0 +1,33 @@
# frozen_string_literal: true
module Spec
module Support
module Helpers
module Features
module MembersHelpers
def members_table
page.find('[data-testid="members-table"]')
end
def all_rows
page.within(members_table) do
page.all('tbody > tr')
end
end
def first_row
all_rows[0]
end
def second_row
all_rows[1]
end
def invite_users_form
page.find('[data-testid="invite-users-form"]')
end
end
end
end
end
end

View file

@ -1,6 +1,8 @@
# frozen_string_literal: true
RSpec.shared_examples 'Maintainer manages access requests' do
include Spec::Support::Helpers::Features::MembersHelpers
let(:user) { create(:user) }
let(:maintainer) { create(:user) }
@ -26,7 +28,7 @@ RSpec.shared_examples 'Maintainer manages access requests' do
expect_no_visible_access_request(entity, user)
page.within('[data-qa-selector="members_list"]') do
page.within(members_table) do
expect(page).to have_content user.name
end
end
@ -35,7 +37,7 @@ RSpec.shared_examples 'Maintainer manages access requests' do
expect_visible_access_request(entity, user)
# Open modal
click_on 'Deny access request'
click_on 'Deny access'
expect(page).not_to have_field "Also unassign this user from related issues and merge requests"