diff options
-rw-r--r-- | app/helpers/sorting_helper.rb | 20 | ||||
-rw-r--r-- | app/helpers/users_helper.rb | 9 | ||||
-rw-r--r-- | app/models/user.rb | 4 | ||||
-rw-r--r-- | app/views/admin/users/_user.html.haml | 55 | ||||
-rw-r--r-- | app/views/admin/users/_user_detail.html.haml | 17 | ||||
-rw-r--r-- | app/views/admin/users/index.html.haml | 96 | ||||
-rw-r--r-- | changelogs/unreleased/43681-display-last-activity-and-created-at-datetimes-for-users-in-admin-users.yml | 5 | ||||
-rw-r--r-- | config/locales/de.yml | 1 | ||||
-rw-r--r-- | config/locales/en.yml | 1 | ||||
-rw-r--r-- | config/locales/es.yml | 1 | ||||
-rw-r--r-- | locale/gitlab.pot | 72 | ||||
-rw-r--r-- | spec/features/admin/admin_users_spec.rb | 42 | ||||
-rw-r--r-- | spec/helpers/users_helper_spec.rb | 68 | ||||
-rw-r--r-- | spec/support/helpers/features/responsive_table_helpers.rb | 32 |
14 files changed, 346 insertions, 77 deletions
diff --git a/app/helpers/sorting_helper.rb b/app/helpers/sorting_helper.rb index 02762897c89..07ec129dea3 100644 --- a/app/helpers/sorting_helper.rb +++ b/app/helpers/sorting_helper.rb @@ -128,7 +128,9 @@ module SortingHelper sort_value_recently_created => sort_title_recently_created, sort_value_oldest_created => sort_title_oldest_created, sort_value_recently_updated => sort_title_recently_updated, - sort_value_oldest_updated => sort_title_oldest_updated + sort_value_oldest_updated => sort_title_oldest_updated, + sort_value_recently_last_activity => sort_title_recently_last_activity, + sort_value_oldest_last_activity => sort_title_oldest_last_activity } end @@ -317,6 +319,14 @@ module SortingHelper s_('SortOptions|Most stars') end + def sort_title_oldest_last_activity + s_('SortOptions|Oldest last activity') + end + + def sort_title_recently_last_activity + s_('SortOptions|Recent last activity') + end + # Values. def sort_value_access_level_asc 'access_level_asc' @@ -445,4 +455,12 @@ module SortingHelper def sort_value_most_stars 'stars_desc' end + + def sort_value_oldest_last_activity + 'last_activity_on_asc' + end + + def sort_value_recently_last_activity + 'last_activity_on_desc' + end end diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb index 73c1402eae5..73ca17c6605 100644 --- a/app/helpers/users_helper.rb +++ b/app/helpers/users_helper.rb @@ -74,6 +74,15 @@ module UsersHelper Gitlab.config.gitlab.impersonation_enabled end + def user_badges_in_admin_section(user) + [].tap do |badges| + badges << { text: s_('AdminUsers|Blocked'), variant: 'danger' } if user.blocked? + badges << { text: s_('AdminUsers|Admin'), variant: 'success' } if user.admin? + badges << { text: s_('AdminUsers|External'), variant: 'secondary' } if user.external? + badges << { text: s_("AdminUsers|It's you!"), variant: nil } if current_user == user + end + end + private def get_profile_tabs diff --git a/app/models/user.rb b/app/models/user.rb index 691abe3175f..9c091ac366c 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -267,6 +267,8 @@ class User < ApplicationRecord scope :without_projects, -> { joins('LEFT JOIN project_authorizations ON users.id = project_authorizations.user_id').where(project_authorizations: { user_id: nil }) } scope :order_recent_sign_in, -> { reorder(Gitlab::Database.nulls_last_order('current_sign_in_at', 'DESC')) } scope :order_oldest_sign_in, -> { reorder(Gitlab::Database.nulls_last_order('current_sign_in_at', 'ASC')) } + scope :order_recent_last_activity, -> { reorder(Gitlab::Database.nulls_last_order('last_activity_on', 'DESC')) } + scope :order_oldest_last_activity, -> { reorder(Gitlab::Database.nulls_first_order('last_activity_on', 'ASC')) } scope :confirmed, -> { where.not(confirmed_at: nil) } scope :by_username, -> (usernames) { iwhere(username: Array(usernames).map(&:to_s)) } scope :for_todos, -> (todos) { where(id: todos.select(:user_id)) } @@ -337,6 +339,8 @@ class User < ApplicationRecord case order_method.to_s when 'recent_sign_in' then order_recent_sign_in when 'oldest_sign_in' then order_oldest_sign_in + when 'last_activity_on_desc' then order_recent_last_activity + when 'last_activity_on_asc' then order_oldest_last_activity else order_by(order_method) end diff --git a/app/views/admin/users/_user.html.haml b/app/views/admin/users/_user.html.haml index a4e2c3252af..be7bfa958b2 100644 --- a/app/views/admin/users/_user.html.haml +++ b/app/views/admin/users/_user.html.haml @@ -1,36 +1,37 @@ -%li.flex-row - .user-avatar - = image_tag avatar_icon_for_user(user), class: "avatar", alt: '' - .row-main-content - .user-name.row-title.str-truncated-100 - = link_to user.name, [:admin, user], class: "js-user-link", data: { user_id: user.id } - - if user.blocked? - %span.badge.badge-danger blocked - - if user.admin? - %span.badge.badge-success Admin - - if user.external? - %span.badge.badge-secondary External - - if user == current_user - %span It's you! - .row-second-line.str-truncated-100 - = mail_to user.email, user.email - .controls - = link_to 'Edit', edit_admin_user_path(user), id: "edit_#{dom_id(user)}", class: 'btn' - - unless user == current_user - .dropdown.inline - %a.dropdown-new.btn.btn-default#project-settings-button{ href: '#', data: { toggle: 'dropdown' } } +.gl-responsive-table-row{ role: 'row' } + .table-section.section-40 + .table-mobile-header{ role: 'rowheader' } + = _('Name') + .table-mobile-content + = render 'user_detail', user: user + .table-section.section-25 + .table-mobile-header{ role: 'rowheader' } + = _('Created on') + .table-mobile-content + = l(user.created_at.to_date, format: :admin) + .table-section.section-15 + .table-mobile-header{ role: 'rowheader' } + = _('Last activity') + .table-mobile-content + = user.last_activity_on.nil? ? _('Never') : l(user.last_activity_on, format: :admin) + .table-section.section-20.table-button-footer + .table-action-buttons + = link_to _('Edit'), edit_admin_user_path(user), id: "edit_#{dom_id(user)}", class: 'btn btn-default' + - unless user == current_user + %button.dropdown-new.btn.btn-default{ type: 'button', data: { toggle: 'dropdown' } } = icon('cog') = icon('caret-down') %ul.dropdown-menu.dropdown-menu-right %li.dropdown-header - Settings + = _('Settings') %li - if user.ldap_blocked? - %span.small Cannot unblock LDAP blocked users + %span.small + = s_('AdminUsers|Cannot unblock LDAP blocked users') - elsif user.blocked? - = link_to 'Unblock', unblock_admin_user_path(user), method: :put + = link_to _('Unblock'), unblock_admin_user_path(user), method: :put - else - = link_to 'Block', block_admin_user_path(user), data: { confirm: 'USER WILL BE BLOCKED! Are you sure?' }, method: :put + = link_to _('Block'), block_admin_user_path(user), data: { confirm: "#{s_('AdminUsers|User will be blocked').upcase}! #{_('Are you sure')}?" }, method: :put - if user.access_locked? %li = link_to _('Unlock'), unlock_admin_user_path(user), method: :put, data: { confirm: _('Are you sure?') } @@ -42,7 +43,7 @@ target: '#delete-user-modal', delete_user_url: admin_user_path(user), block_user_url: block_admin_user_path(user), - username: user.name, + username: sanitize_name(user.name), delete_contributions: false }, type: 'button' } = s_('AdminUsers|Delete user') @@ -51,6 +52,6 @@ target: '#delete-user-modal', delete_user_url: admin_user_path(user, hard_delete: true), block_user_url: block_admin_user_path(user), - username: user.name, + username: sanitize_name(user.name), delete_contributions: true }, type: 'button' } = s_('AdminUsers|Delete user and contributions') diff --git a/app/views/admin/users/_user_detail.html.haml b/app/views/admin/users/_user_detail.html.haml new file mode 100644 index 00000000000..3319b4bad3a --- /dev/null +++ b/app/views/admin/users/_user_detail.html.haml @@ -0,0 +1,17 @@ +.flex-list + .flex-row + = image_tag avatar_icon_for_user(user), class: 'avatar s32 d-none d-md-flex', alt: _('Avatar for %{name}') % { name: sanitize_name(user.name) } + .row-main-content + .row-title.str-truncated-100 + = image_tag avatar_icon_for_user(user), class: 'avatar s16 d-xs-flex d-md-none mr-1 prepend-top-2', alt: _('Avatar for %{name}') % { name: sanitize_name(user.name) } + = link_to user.name, admin_user_path(user), class: 'text-plain js-user-link', data: { user_id: user.id } + + = render_if_exists 'admin/users/user_detail_note', user: user + + - user_badges_in_admin_section(user).each do |badge| + - css_badge = "badge badge-#{badge[:variant]}" if badge[:variant].present? + %span{ class: css_badge } + = badge[:text] + + .row-second-line.str-truncated-100 + = mail_to user.email, user.email, class: 'text-secondary' diff --git a/app/views/admin/users/index.html.haml b/app/views/admin/users/index.html.haml index 600120c4f05..c3d5ce0fe70 100644 --- a/app/views/admin/users/index.html.haml +++ b/app/views/admin/users/index.html.haml @@ -2,72 +2,78 @@ - page_title "Users" %div{ class: container_class } - .prepend-top-default + .top-area.scrolling-tabs-container.inner-page-scroll-tabs + .fade-left + = icon('angle-left') + .fade-right + = icon('angle-right') + %ul.nav-links.nav.nav-tabs.scrolling-tabs + = nav_link(html_options: { class: active_when(params[:filter].nil?) }) do + = link_to admin_users_path do + = s_('AdminUsers|Active') + %small.badge.badge-pill= limited_counter_with_delimiter(User.active) + = nav_link(html_options: { class: active_when(params[:filter] == 'admins') }) do + = link_to admin_users_path(filter: "admins") do + = s_('AdminUsers|Admins') + %small.badge.badge-pill= limited_counter_with_delimiter(User.admins) + = nav_link(html_options: { class: "#{active_when(params[:filter] == 'two_factor_enabled')} filter-two-factor-enabled" }) do + = link_to admin_users_path(filter: 'two_factor_enabled') do + = s_('AdminUsers|2FA Enabled') + %small.badge.badge-pill= limited_counter_with_delimiter(User.with_two_factor) + = nav_link(html_options: { class: "#{active_when(params[:filter] == 'two_factor_disabled')} filter-two-factor-disabled" }) do + = link_to admin_users_path(filter: 'two_factor_disabled') do + = s_('AdminUsers|2FA Disabled') + %small.badge.badge-pill= limited_counter_with_delimiter(User.without_two_factor) + = nav_link(html_options: { class: active_when(params[:filter] == 'external') }) do + = link_to admin_users_path(filter: 'external') do + = s_('AdminUsers|External') + %small.badge.badge-pill= limited_counter_with_delimiter(User.external) + = nav_link(html_options: { class: active_when(params[:filter] == 'blocked') }) do + = link_to admin_users_path(filter: "blocked") do + = s_('AdminUsers|Blocked') + %small.badge.badge-pill= limited_counter_with_delimiter(User.blocked) + = nav_link(html_options: { class: active_when(params[:filter] == 'wop') }) do + = link_to admin_users_path(filter: "wop") do + = s_('AdminUsers|Without projects') + %small.badge.badge-pill= limited_counter_with_delimiter(User.without_projects) + .nav-controls + = render_if_exists 'admin/users/admin_email_users' + = link_to s_('AdminUsers|New user'), new_admin_user_path, class: 'btn btn-success btn-search float-right' + + .filtered-search-block.row-content-block.border-top-0 = form_tag admin_users_path, method: :get do - if params[:filter].present? = hidden_field_tag "filter", h(params[:filter]) .search-holder .search-field-holder - = search_field_tag :search_query, params[:search_query], placeholder: 'Search by name, email or username', class: 'form-control search-text-input js-search-input', spellcheck: false + = search_field_tag :search_query, params[:search_query], placeholder: s_('AdminUsers|Search by name, email or username'), class: 'form-control search-text-input js-search-input', spellcheck: false - if @sort.present? = hidden_field_tag :sort, @sort = icon("search", class: "search-icon") - = button_tag 'Search users' if Rails.env.test? + = button_tag s_('AdminUsers|Search users') if Rails.env.test? .dropdown.user-sort-dropdown - toggle_text = if @sort.present? then users_sort_options_hash[@sort] else sort_title_name end = dropdown_toggle(toggle_text, { toggle: 'dropdown' }) %ul.dropdown-menu.dropdown-menu-right %li.dropdown-header - Sort by + = s_('AdminUsers|Sort by') %li - users_sort_options_hash.each do |value, title| = link_to admin_users_path(sort: value, filter: params[:filter], search_query: params[:search_query]) do = title - = link_to 'New user', new_admin_user_path, class: 'btn btn-success btn-search' - .top-area.scrolling-tabs-container.inner-page-scroll-tabs - .fade-left - = icon('angle-left') - .fade-right - = icon('angle-right') - %ul.nav-links.nav.nav-tabs.scrolling-tabs - = nav_link(html_options: { class: active_when(params[:filter].nil?) }) do - = link_to admin_users_path do - Active - %small.badge.badge-pill= limited_counter_with_delimiter(User.active) - = nav_link(html_options: { class: active_when(params[:filter] == 'admins') }) do - = link_to admin_users_path(filter: "admins") do - Admins - %small.badge.badge-pill= limited_counter_with_delimiter(User.admins) - = nav_link(html_options: { class: "#{active_when(params[:filter] == 'two_factor_enabled')} filter-two-factor-enabled" }) do - = link_to admin_users_path(filter: 'two_factor_enabled') do - 2FA Enabled - %small.badge.badge-pill= limited_counter_with_delimiter(User.with_two_factor) - = nav_link(html_options: { class: "#{active_when(params[:filter] == 'two_factor_disabled')} filter-two-factor-disabled" }) do - = link_to admin_users_path(filter: 'two_factor_disabled') do - 2FA Disabled - %small.badge.badge-pill= limited_counter_with_delimiter(User.without_two_factor) - = nav_link(html_options: { class: active_when(params[:filter] == 'external') }) do - = link_to admin_users_path(filter: 'external') do - External - %small.badge.badge-pill= limited_counter_with_delimiter(User.external) - = nav_link(html_options: { class: active_when(params[:filter] == 'blocked') }) do - = link_to admin_users_path(filter: "blocked") do - Blocked - %small.badge.badge-pill= limited_counter_with_delimiter(User.blocked) - = nav_link(html_options: { class: active_when(params[:filter] == 'wop') }) do - = link_to admin_users_path(filter: "wop") do - Without projects - %small.badge.badge-pill= limited_counter_with_delimiter(User.without_projects) + - if @users.empty? + .nothing-here-block.border-top-0 + = s_('AdminUsers|No users found') + - else + .table-holder + .thead-white.text-nowrap.gl-responsive-table-row.table-row-header{ role: 'row' } + .table-section.section-40{ role: 'rowheader' }= _('Name') + .table-section.section-25{ role: 'rowheader' }= _('Created on') + .table-section.section-15{ role: 'rowheader' }= _('Last activity') - %ul.flex-list.content-list - - if @users.empty? - %li - .nothing-here-block No users found. - - else = render partial: 'admin/users/user', collection: @users = paginate @users, theme: "gitlab" #delete-user-modal - diff --git a/changelogs/unreleased/43681-display-last-activity-and-created-at-datetimes-for-users-in-admin-users.yml b/changelogs/unreleased/43681-display-last-activity-and-created-at-datetimes-for-users-in-admin-users.yml new file mode 100644 index 00000000000..0fbf6314a27 --- /dev/null +++ b/changelogs/unreleased/43681-display-last-activity-and-created-at-datetimes-for-users-in-admin-users.yml @@ -0,0 +1,5 @@ +--- +title: Display last activity and created at datetimes for users +merge_request: 24181 +author: +type: added diff --git a/config/locales/de.yml b/config/locales/de.yml index 38c3711c6c7..554e9913faa 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -43,6 +43,7 @@ de: default: "%d.%m.%Y" long: "%e. %B %Y" short: "%e. %b" + admin: "%e %b, %Y" month_names: - - Januar diff --git a/config/locales/en.yml b/config/locales/en.yml index 0a43a1d9a6b..e8dbc033a7c 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -55,6 +55,7 @@ en: default: "%Y-%m-%d" long: "%B %d, %Y" short: "%b %d" + admin: "%e %b, %Y" month_names: - - January diff --git a/config/locales/es.yml b/config/locales/es.yml index fdc52b4ae11..78c07583933 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -42,6 +42,7 @@ es: default: "%d/%m/%Y" long: "%d de %B de %Y" short: "%d de %b" + admin: "%e %b, %Y" month_names: - - enero diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 1caf263b9f3..9ec590f90d8 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -468,9 +468,30 @@ msgstr "" msgid "AdminSettings|When creating a new environment variable it will be protected by default." msgstr "" +msgid "AdminUsers|2FA Disabled" +msgstr "" + +msgid "AdminUsers|2FA Enabled" +msgstr "" + +msgid "AdminUsers|Active" +msgstr "" + +msgid "AdminUsers|Admin" +msgstr "" + +msgid "AdminUsers|Admins" +msgstr "" + msgid "AdminUsers|Block user" msgstr "" +msgid "AdminUsers|Blocked" +msgstr "" + +msgid "AdminUsers|Cannot unblock LDAP blocked users" +msgstr "" + msgid "AdminUsers|Delete User %{username} and contributions?" msgstr "" @@ -483,12 +504,39 @@ msgstr "" msgid "AdminUsers|Delete user and contributions" msgstr "" +msgid "AdminUsers|External" +msgstr "" + +msgid "AdminUsers|It's you!" +msgstr "" + +msgid "AdminUsers|New user" +msgstr "" + +msgid "AdminUsers|No users found" +msgstr "" + +msgid "AdminUsers|Search by name, email or username" +msgstr "" + +msgid "AdminUsers|Search users" +msgstr "" + +msgid "AdminUsers|Sort by" +msgstr "" + msgid "AdminUsers|To confirm, type %{projectName}" msgstr "" msgid "AdminUsers|To confirm, type %{username}" msgstr "" +msgid "AdminUsers|User will be blocked" +msgstr "" + +msgid "AdminUsers|Without projects" +msgstr "" + msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings." msgstr "" @@ -711,6 +759,9 @@ msgstr "" msgid "Archived projects" msgstr "" +msgid "Are you sure" +msgstr "" + msgid "Are you sure you want to delete this pipeline schedule?" msgstr "" @@ -909,6 +960,9 @@ msgstr "" msgid "Avatar for %{assigneeName}" msgstr "" +msgid "Avatar for %{name}" +msgstr "" + msgid "Avatar will be removed. Are you sure?" msgstr "" @@ -1014,6 +1068,9 @@ msgstr "" msgid "Bitbucket import" msgstr "" +msgid "Block" +msgstr "" + msgid "Blocked" msgstr "" @@ -2348,6 +2405,9 @@ msgstr "" msgid "Created by me" msgstr "" +msgid "Created on" +msgstr "" + msgid "Created on:" msgstr "" @@ -4124,6 +4184,9 @@ msgstr[1] "" msgid "Last Pipeline" msgstr "" +msgid "Last activity" +msgstr "" + msgid "Last commit" msgstr "" @@ -6668,6 +6731,9 @@ msgstr "" msgid "SortOptions|Oldest joined" msgstr "" +msgid "SortOptions|Oldest last activity" +msgstr "" + msgid "SortOptions|Oldest sign in" msgstr "" @@ -6680,6 +6746,9 @@ msgstr "" msgid "SortOptions|Priority" msgstr "" +msgid "SortOptions|Recent last activity" +msgstr "" + msgid "SortOptions|Recent sign in" msgstr "" @@ -7668,6 +7737,9 @@ msgstr "" msgid "Unable to load the diff. %{button_try_again}" msgstr "" +msgid "Unblock" +msgstr "" + msgid "Undo" msgstr "" diff --git a/spec/features/admin/admin_users_spec.rb b/spec/features/admin/admin_users_spec.rb index 931095936a6..b1c6f308bc6 100644 --- a/spec/features/admin/admin_users_spec.rb +++ b/spec/features/admin/admin_users_spec.rb @@ -1,13 +1,13 @@ require 'spec_helper' describe "Admin::Users" do - include Spec::Support::Helpers::Features::ListRowsHelpers + include Spec::Support::Helpers::Features::ResponsiveTableHelpers let!(:user) do create(:omniauth_user, provider: 'twitter', extern_uid: '123456') end - let!(:current_user) { create(:admin) } + let!(:current_user) { create(:admin, last_activity_on: 5.days.ago) } before do sign_in(current_user) @@ -25,6 +25,8 @@ describe "Admin::Users" do it "has users list" do expect(page).to have_content(current_user.email) expect(page).to have_content(current_user.name) + expect(page).to have_content(current_user.created_at.strftime("%e %b, %Y")) + expect(page).to have_content(current_user.last_activity_on.strftime("%e %b, %Y")) expect(page).to have_content(user.email) expect(page).to have_content(user.name) expect(page).to have_link('Block', href: block_admin_user_path(user)) @@ -32,10 +34,24 @@ describe "Admin::Users" do expect(page).to have_button('Delete user and contributions') end + describe "view extra user information", :js do + it 'does not have the user popover open' do + expect(page).not_to have_selector('#__BV_popover_1__') + end + + it 'shows the user popover on hover' do + first_user_link = page.first('.js-user-link') + + first_user_link.hover + + expect(page).to have_selector('#__BV_popover_1__') + end + end + describe 'search and sort' do before do - create(:user, name: 'Foo Bar') - create(:user, name: 'Foo Baz') + create(:user, name: 'Foo Bar', last_activity_on: 3.days.ago) + create(:user, name: 'Foo Baz', last_activity_on: 2.days.ago) create(:user, name: 'Dmitriy') end @@ -75,6 +91,24 @@ describe "Admin::Users" do expect(first_row.text).to include('Foo Bar') expect(second_row.text).to include('Foo Baz') end + + it 'sorts users by recent last activity' do + visit admin_users_path(search_query: 'Foo') + + sort_by('Recent last activity') + + expect(first_row.text).to include('Foo Baz') + expect(second_row.text).to include('Foo Bar') + end + + it 'sorts users by oldest last activity' do + visit admin_users_path(search_query: 'Foo') + + sort_by('Oldest last activity') + + expect(first_row.text).to include('Foo Bar') + expect(second_row.text).to include('Foo Baz') + end end describe 'Two-factor Authentication filters' do diff --git a/spec/helpers/users_helper_spec.rb b/spec/helpers/users_helper_spec.rb index ab67a5ab847..f3649495493 100644 --- a/spec/helpers/users_helper_spec.rb +++ b/spec/helpers/users_helper_spec.rb @@ -100,4 +100,72 @@ describe UsersHelper do end end end + + describe '#user_badges_in_admin_section' do + before do + allow(helper).to receive(:current_user).and_return(user) + end + + context 'with a blocked user' do + it "returns the blocked badge" do + blocked_user = create(:user, state: 'blocked') + + badges = helper.user_badges_in_admin_section(blocked_user) + + expect(badges).to eq([text: "Blocked", variant: "danger"]) + end + end + + context 'with an admin user' do + it "returns the admin badge" do + admin_user = create(:admin) + + badges = helper.user_badges_in_admin_section(admin_user) + + expect(badges).to eq([text: "Admin", variant: "success"]) + end + end + + context 'with an external user' do + it 'returns the external badge' do + external_user = create(:user, external: true) + + badges = helper.user_badges_in_admin_section(external_user) + + expect(badges).to eq([text: "External", variant: "secondary"]) + end + end + + context 'with the current user' do + it 'returns the "It\'s You" badge' do + badges = helper.user_badges_in_admin_section(user) + + expect(badges).to eq([text: "It's you!", variant: nil]) + end + end + + context 'with an external blocked admin' do + it 'returns the blocked, admin and external badges' do + user = create(:admin, state: 'blocked', external: true) + + badges = helper.user_badges_in_admin_section(user) + + expect(badges).to eq([ + { text: "Blocked", variant: "danger" }, + { text: "Admin", variant: "success" }, + { text: "External", variant: "secondary" } + ]) + end + end + + context 'get badges for normal user' do + it 'returns no badges' do + user = create(:user) + + badges = helper.user_badges_in_admin_section(user) + + expect(badges).to be_empty + end + end + end end diff --git a/spec/support/helpers/features/responsive_table_helpers.rb b/spec/support/helpers/features/responsive_table_helpers.rb new file mode 100644 index 00000000000..7a175219fe9 --- /dev/null +++ b/spec/support/helpers/features/responsive_table_helpers.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true +# These helpers allow you to access rows in a responsive table +# +# Usage: +# describe "..." do +# include Spec::Support::Helpers::Features::ResponsiveTableHelpers +# ... +# +# expect(first_row.text).to include("John Doe") +# expect(second_row.text).to include("John Smith") +# +# Note: +# index starts at 1 as index 0 is expected to be the table header +# +# +module Spec + module Support + module Helpers + module Features + module ResponsiveTableHelpers + def first_row + page.all('.gl-responsive-table-row')[1] + end + + def second_row + page.all('.gl-responsive-table-row')[2] + end + end + end + end + end +end |