ee/spec/features/admin/admin_credentials_spec.rb (228 lines of code) (raw):

# frozen_string_literal: true require 'spec_helper' RSpec.describe 'Admin::Credentials', :with_current_organization, feature_category: :user_management do include Features::AdminUsersHelpers let_it_be(:admin) { create(:admin, organizations: [current_organization]) } before do sign_in(admin) enable_admin_mode!(admin) stub_licensed_features(credentials_inventory: true) end describe 'GET /admin/credentials' do before do visit admin_credentials_path end it "is ok and shows no personal access tokens" do expect(page).to have_current_path(admin_credentials_path) expect(page).to have_content(s_('CredentialsInventory|No credentials found')) end describe 'search and filter', :js do before_all do create(:personal_access_token, name: 'my personal access token', user: admin, scopes: [:read_api], expires_at: 10.days.from_now) create(:personal_access_token, user: admin, scopes: [:manage_runner], revoked: true, expires_at: 10.days.from_now) create(:personal_access_token, user: admin, scopes: [:k8s_proxy], created_at: 1.day.ago, expires_at: 10.days.from_now) create(:personal_access_token, user: admin, scopes: [:read_repository], created_at: 1.day.from_now, expires_at: 10.days.from_now) create(:personal_access_token, user: admin, scopes: [:write_repository], last_used_at: 2.days.ago, expires_at: 10.days.from_now) create(:personal_access_token, user: admin, scopes: [:ai_features], last_used_at: 1.day.ago, expires_at: 10.days.from_now) create(:personal_access_token, user: admin, scopes: [:create_runner], expires_at: 2.days.from_now) create(:personal_access_token, user: admin, scopes: [:sudo], expires_at: 200.days.from_now) end it 'searches by token name' do expect_all_rows input_filtered_search_keys('my personal access token') expect_one_row_with_content('read_api') end it 'filters by type' do expect_all_rows input_filtered_search_filter_is_only(s_('CredentialsInventory|Type'), s_('CredentialsInventory|SSH keys')) expect(page).to have_content(s_('CredentialsInventory|No credentials found')) end it 'filters by state' do expect_all_rows input_filtered_search_filter_is_only(s_('CredentialsInventory|State'), s_('CredentialsInventory|Inactive')) expect_one_row_with_content('manage_runner') end it 'filters by revoke' do expect_all_rows input_filtered_search_filter_is_only(s_('CredentialsInventory|Revoked'), s_('CredentialsInventory|Yes')) expect_one_row_with_content('manage_runner') end describe 'created date' do it 'filters date before' do expect_all_rows input_filtered_search_filter_is_before(s_('CredentialsInventory|Created date'), 0.days.ago.to_date) expect_one_row_with_content('k8s_proxy') end it 'filters by date after' do expect_all_rows input_filtered_search_filter_is_after(s_('CredentialsInventory|Created date'), 1.day.from_now.to_date) expect_one_row_with_content('read_repository') end end describe 'expiration date' do it 'filters date before' do expect_all_rows input_filtered_search_filter_is_before(s_('CredentialsInventory|Expiration date'), 3.days.from_now.to_date) expect_one_row_with_content('create_runner') end it 'filters by date after' do expect_all_rows input_filtered_search_filter_is_after(s_('CredentialsInventory|Expiration date'), 200.days.from_now.to_date) expect_one_row_with_content('sudo') end end describe 'last used date' do it 'filters date before' do expect_all_rows input_filtered_search_filter_is_before(s_('CredentialsInventory|Last used date'), 1.day.ago.to_date) expect_one_row_with_content('write_repository') end it 'filters by date after' do expect_all_rows input_filtered_search_filter_is_after(s_('CredentialsInventory|Last used date'), 1.day.ago.to_date) expect_one_row_with_content('ai_features') end end describe 'shows correct search and filters based on the URL parameters' do it 'shows search' do visit admin_credentials_path(search: 'my personal access token') within_testid(filtered_search) do expect(page).to have_content('my personal access token') end end it 'shows type filter' do visit admin_credentials_path(filter: 'personal_access_tokens') within_testid(filtered_search) do expect(page).to have_content( "#{s_('CredentialsInventory|Type')} = #{s_('CredentialsInventory|Personal access tokens')}") end end it 'shows state filter' do visit admin_credentials_path(state: 'active') within_testid(filtered_search) do expect(page).to have_content("#{s_('CredentialsInventory|State')} = #{s_('CredentialsInventory|Active')}") end end it 'shows revoked filter' do visit admin_credentials_path(revoked: 'true') within_testid(filtered_search) do expect(page).to have_content("#{s_('CredentialsInventory|Revoked')} = #{s_('CredentialsInventory|Yes')}") end end describe 'created date' do it 'shows created date before filter' do visit admin_credentials_path(created_before: '2025-01-01') within_testid(filtered_search) do expect(page).to have_content("#{s_('CredentialsInventory|Created date')} < 2025-01-01") end end it 'shows created date before filter' do visit admin_credentials_path(created_after: '2025-01-01') within_testid(filtered_search) do expect(page).to have_content("#{s_('CredentialsInventory|Created date')} ≥ 2025-01-01") end end end describe 'expiration date' do it 'shows created date before filter' do visit admin_credentials_path(expires_before: '2025-01-01') within_testid(filtered_search) do expect(page).to have_content("#{s_('CredentialsInventory|Expiration date')} < 2025-01-01") end end it 'shows created date before filter' do visit admin_credentials_path(expires_after: '2025-01-01') within_testid(filtered_search) do expect(page).to have_content("#{s_('CredentialsInventory|Expiration date')} ≥ 2025-01-01") end end end describe 'last used date' do it 'shows last used date before filter' do visit admin_credentials_path(last_used_before: '2025-01-01') within_testid(filtered_search) do expect(page).to have_content("#{s_('CredentialsInventory|Last used date')} < 2025-01-01") end end it 'shows last used date before filter' do visit admin_credentials_path(last_used_after: '2025-01-01') within_testid(filtered_search) do expect(page).to have_content("#{s_('CredentialsInventory|Last used date')} ≥ 2025-01-01") end end end it 'ignores unknown filters' do visit admin_credentials_path(my_filter: 'true') within_testid(filtered_search) do expect(page).to have_content('') end end end end end def content_body '#content-body' end def expect_all_rows within(content_body) do expect(all_rows.size).to eq(8) end end def expect_one_row_with_content(content) within(content_body) do expect(all_rows.size).to eq(1) expect(page).to have_content(content) end end def all_rows page.all('.table-holder .gl-responsive-table-row:not(.table-row-header)[role="row"]') end def filtered_search 'filtered-search-input' end # The filters must be clicked first to be able to receive events # See: https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1493 def focus_filtered_search page.find('.gl-filtered-search-term-token').click end def input_filtered_search_keys(search_term) within_testid(filtered_search) do focus_filtered_search send_keys(search_term) send_keys(:enter) click_on 'Search' end end def input_filtered_search_filter_is_only(filter, value) within_testid(filtered_search) do focus_filtered_search click_on filter # For OPERATORS_IS, clicking the filter # immediately preselects "=" operator send_keys(value) send_keys(:enter) click_on 'Search' end end def input_filtered_search_filter_is_before(filter, value) within_testid(filtered_search) do focus_filtered_search click_on filter send_keys('<') send_keys(value) send_keys(:enter) click_on 'Search' end end def input_filtered_search_filter_is_after(filter, value) within_testid(filtered_search) do focus_filtered_search click_on filter send_keys('≥') send_keys(value) send_keys(:enter) click_on 'Search' end end end