diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-10-20 21:09:10 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-10-20 21:09:10 +0300 |
commit | a3764262c04bafcd6a54aff635541d73a8a630fd (patch) | |
tree | ea54444857967f08b7601886b47d15819990b6cf /spec | |
parent | 049d16d168fdee408b78f5f38619c092fd3b2265 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
14 files changed, 274 insertions, 226 deletions
diff --git a/spec/features/issues/user_sorts_issues_spec.rb b/spec/features/issues/user_sorts_issues_spec.rb index 7add6c782f7..2716d742be3 100644 --- a/spec/features/issues/user_sorts_issues_spec.rb +++ b/spec/features/issues/user_sorts_issues_spec.rb @@ -24,7 +24,7 @@ RSpec.describe "User sorts issues" do sign_in(user) end - it 'keeps the sort option', :js do + it 'keeps the sort option', :js, quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/378184' do visit(project_issues_path(project)) click_button 'Created date' diff --git a/spec/frontend/pipeline_schedules/components/pipeline_schedules_spec.js b/spec/frontend/pipeline_schedules/components/pipeline_schedules_spec.js index cce8f480928..2a7ccce1092 100644 --- a/spec/frontend/pipeline_schedules/components/pipeline_schedules_spec.js +++ b/spec/frontend/pipeline_schedules/components/pipeline_schedules_spec.js @@ -1,9 +1,10 @@ -import { GlAlert, GlLoadingIcon, GlModal } from '@gitlab/ui'; -import { shallowMount } from '@vue/test-utils'; +import { GlAlert, GlLoadingIcon, GlModal, GlTabs } from '@gitlab/ui'; import Vue, { nextTick } from 'vue'; import VueApollo from 'vue-apollo'; +import { trimText } from 'helpers/text_helper'; import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; +import { mountExtended } from 'helpers/vue_test_utils_helper'; import PipelineSchedules from '~/pipeline_schedules/components/pipeline_schedules.vue'; import PipelineSchedulesTable from '~/pipeline_schedules/components/table/pipeline_schedules_table.vue'; import deletePipelineScheduleMutation from '~/pipeline_schedules/graphql/mutations/delete_pipeline_schedule.mutation.graphql'; @@ -32,7 +33,7 @@ describe('Pipeline schedules app', () => { }; const createComponent = (requestHandlers) => { - wrapper = shallowMount(PipelineSchedules, { + wrapper = mountExtended(PipelineSchedules, { provide: { fullPath: 'gitlab-org/gitlab', }, @@ -44,17 +45,24 @@ describe('Pipeline schedules app', () => { const findAlert = () => wrapper.findComponent(GlAlert); const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon); const findModal = () => wrapper.findComponent(GlModal); + const findTabs = () => wrapper.findComponent(GlTabs); + const findNewButton = () => wrapper.findByTestId('new-schedule-button'); + const findAllTab = () => wrapper.findByTestId('pipeline-schedules-all-tab'); + const findActiveTab = () => wrapper.findByTestId('pipeline-schedules-active-tab'); + const findInactiveTab = () => wrapper.findByTestId('pipeline-schedules-inactive-tab'); afterEach(() => { wrapper.destroy(); }); - it('displays table', async () => { + it('displays table, tabs and new button', async () => { createComponent(); await waitForPromises(); expect(findTable().exists()).toBe(true); + expect(findNewButton().exists()).toBe(true); + expect(findTabs().exists()).toBe(true); expect(findAlert().exists()).toBe(false); }); @@ -158,4 +166,38 @@ describe('Pipeline schedules app', () => { expect(findModal().props('visible')).toBe(false); }); + + describe('tabs', () => { + beforeEach(async () => { + createComponent(); + + await waitForPromises(); + }); + + it('displays All tab with count', () => { + expect(trimText(findAllTab().text())).toBe(`All ${mockPipelineScheduleNodes.length}`); + }); + + it('displays Active tab with no count', () => { + expect(findActiveTab().text()).toBe('Active'); + }); + + it('displays Inactive tab with no count', () => { + expect(findInactiveTab().text()).toBe('Inactive'); + }); + }); + + it('should refetch the schedules query on a tab click', async () => { + createComponent(); + + await waitForPromises(); + + jest.spyOn(wrapper.vm.$apollo.queries.schedules, 'refetch').mockImplementation(jest.fn()); + + expect(wrapper.vm.$apollo.queries.schedules.refetch).toHaveBeenCalledTimes(0); + + await findAllTab().trigger('click'); + + expect(wrapper.vm.$apollo.queries.schedules.refetch).toHaveBeenCalledTimes(1); + }); }); diff --git a/spec/lib/gitlab/ci/variables/collection_spec.rb b/spec/lib/gitlab/ci/variables/collection_spec.rb index 7d4a1eef70b..4710698fd95 100644 --- a/spec/lib/gitlab/ci/variables/collection_spec.rb +++ b/spec/lib/gitlab/ci/variables/collection_spec.rb @@ -601,7 +601,8 @@ RSpec.describe Gitlab::Ci::Variables::Collection do it 'logs file_variable_is_referenced_in_another_variable once for VAR5' do expect(Gitlab::AppJsonLogger).to receive(:info).with( event: 'file_variable_is_referenced_in_another_variable', - project_id: project.id + project_id: project.id, + variable: 'FILEVAR4' ).once sort_and_expand_all diff --git a/spec/lib/gitlab/database/partitioning_migration_helpers/index_helpers_spec.rb b/spec/lib/gitlab/database/partitioning_migration_helpers/index_helpers_spec.rb index 7465f69b87c..5d02266e8a2 100644 --- a/spec/lib/gitlab/database/partitioning_migration_helpers/index_helpers_spec.rb +++ b/spec/lib/gitlab/database/partitioning_migration_helpers/index_helpers_spec.rb @@ -231,4 +231,165 @@ RSpec.describe Gitlab::Database::PartitioningMigrationHelpers::IndexHelpers do end end end + + describe '#indexes_by_definition_for_table' do + context 'when a partitioned table has indexes' do + subject do + migration.indexes_by_definition_for_table(table_name) + end + + before do + connection.execute(<<~SQL) + CREATE INDEX #{index_name} ON #{table_name} (#{column_name}); + SQL + end + + it 'captures partitioned index names by index definition' do + expect(subject).to match(a_hash_including({ "CREATE _ btree (#{column_name})" => index_name })) + end + end + + context 'when a non-partitioned table has indexes' do + let(:regular_table_name) { '_test_regular_table' } + let(:regular_index_name) { '_test_regular_index_name' } + + subject do + migration.indexes_by_definition_for_table(regular_table_name) + end + + before do + connection.execute(<<~SQL) + CREATE TABLE #{regular_table_name} ( + #{column_name} timestamptz NOT NULL + ); + + CREATE INDEX #{regular_index_name} ON #{regular_table_name} (#{column_name}); + SQL + end + + it 'captures index names by index definition' do + expect(subject).to match(a_hash_including({ "CREATE _ btree (#{column_name})" => regular_index_name })) + end + end + + context 'when a non-partitioned table has duplicate indexes' do + let(:regular_table_name) { '_test_regular_table' } + let(:regular_index_name) { '_test_regular_index_name' } + let(:duplicate_index_name) { '_test_duplicate_index_name' } + + subject do + migration.indexes_by_definition_for_table(regular_table_name) + end + + before do + connection.execute(<<~SQL) + CREATE TABLE #{regular_table_name} ( + #{column_name} timestamptz NOT NULL + ); + + CREATE INDEX #{regular_index_name} ON #{regular_table_name} (#{column_name}); + CREATE INDEX #{duplicate_index_name} ON #{regular_table_name} (#{column_name}); + SQL + end + + it 'raises an error' do + expect { subject }.to raise_error { described_class::DuplicatedIndexesError } + end + end + end + + describe '#rename_indexes_for_table' do + let(:original_table_name) { '_test_rename_indexes_table' } + let(:first_partition_name) { '_test_rename_indexes_table_1' } + let(:transient_table_name) { '_test_rename_indexes_table_child' } + let(:custom_column_name) { 'created_at' } + let(:generated_column_name) { 'updated_at' } + let(:custom_index_name) { 'index_test_rename_indexes_table_on_created_at' } + let(:custom_index_name_regenerated) { '_test_rename_indexes_table_created_at_idx' } + let(:generated_index_name) { '_test_rename_indexes_table_updated_at_idx' } + let(:generated_index_name_collided) { '_test_rename_indexes_table_updated_at_idx1' } + + before do + connection.execute(<<~SQL) + CREATE TABLE #{original_table_name} ( + #{custom_column_name} timestamptz NOT NULL, + #{generated_column_name} timestamptz NOT NULL + ); + + CREATE INDEX #{custom_index_name} ON #{original_table_name} (#{custom_column_name}); + CREATE INDEX ON #{original_table_name} (#{generated_column_name}); + SQL + end + + context 'when changing a table within the current schema' do + let!(:identifiers) { migration.indexes_by_definition_for_table(original_table_name) } + + before do + connection.execute(<<~SQL) + ALTER TABLE #{original_table_name} RENAME TO #{first_partition_name}; + CREATE TABLE #{original_table_name} (LIKE #{first_partition_name} INCLUDING ALL); + DROP TABLE #{first_partition_name}; + SQL + end + + it 'maps index names after they are changed' do + migration.rename_indexes_for_table(original_table_name, identifiers) + + expect_index_to_exist(custom_index_name) + expect_index_to_exist(generated_index_name) + end + + it 'does not rename an index which does not exist in the to_hash' do + partial_identifiers = identifiers.reject { |_, name| name == custom_index_name } + + migration.rename_indexes_for_table(original_table_name, partial_identifiers) + + expect_index_not_to_exist(custom_index_name) + expect_index_to_exist(generated_index_name) + end + end + + context 'when partitioning an existing table' do + before do + connection.execute(<<~SQL) + /* Create new parent table */ + CREATE TABLE #{first_partition_name} (LIKE #{original_table_name} INCLUDING ALL); + SQL + end + + it 'renames indexes across schemas' do + # Capture index names generated by postgres + generated_index_names = migration.indexes_by_definition_for_table(first_partition_name) + + # Capture index names from original table + original_index_names = migration.indexes_by_definition_for_table(original_table_name) + + connection.execute(<<~SQL) + /* Rename original table out of the way */ + ALTER TABLE #{original_table_name} RENAME TO #{transient_table_name}; + + /* Rename new parent table to original name */ + ALTER TABLE #{first_partition_name} RENAME TO #{original_table_name}; + + /* Move original table to gitlab_partitions_dynamic schema */ + ALTER TABLE #{transient_table_name} SET SCHEMA #{partition_schema}; + + /* Rename original table to be the first partition */ + ALTER TABLE #{partition_schema}.#{transient_table_name} RENAME TO #{first_partition_name}; + SQL + + # Apply index names generated by postgres to first partition + migration.rename_indexes_for_table(first_partition_name, generated_index_names, schema_name: partition_schema) + + expect_index_to_exist('_test_rename_indexes_table_1_created_at_idx') + expect_index_to_exist('_test_rename_indexes_table_1_updated_at_idx') + + # Apply index names from original table to new parent table + migration.rename_indexes_for_table(original_table_name, original_index_names) + + expect_index_to_exist(custom_index_name) + expect_index_to_exist(generated_index_name) + end + end + end end diff --git a/spec/migrations/cleanup_vulnerability_state_transitions_with_same_from_state_to_state_spec.rb b/spec/migrations/cleanup_vulnerability_state_transitions_with_same_from_state_to_state_spec.rb new file mode 100644 index 00000000000..92ece81ffc8 --- /dev/null +++ b/spec/migrations/cleanup_vulnerability_state_transitions_with_same_from_state_to_state_spec.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +require 'spec_helper' +require_migration! + +RSpec.describe CleanupVulnerabilityStateTransitionsWithSameFromStateToState, :migration do + let_it_be(:namespace) { table(:namespaces).create!(name: 'namespace', type: 'Group', path: 'namespace') } + let_it_be(:user) { table(:users).create!(email: 'author@example.com', username: 'author', projects_limit: 10) } + let_it_be(:project) do + table(:projects).create!( + path: 'project', + namespace_id: namespace.id, + project_namespace_id: namespace.id + ) + end + + let_it_be(:vulnerability) do + table(:vulnerabilities).create!( + project_id: project.id, + author_id: user.id, + title: 'test', + severity: 7, + confidence: 7, + report_type: 0 + ) + end + + let_it_be(:state_transitions) { table(:vulnerability_state_transitions) } + + let!(:state_transition_with_no_state_change) do + state_transitions.create!( + vulnerability_id: vulnerability.id, + from_state: 2, + to_state: 2 + ) + end + + let!(:state_transition_with_state_change) do + state_transitions.create!( + vulnerability_id: vulnerability.id, + from_state: 1, + to_state: 2 + ) + end + + it 'deletes state transitions with no state change' do + expect { migrate! }.to change(state_transitions, :count).from(2).to(1) + end +end diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb index c6d028af22d..838e5d700c1 100644 --- a/spec/models/namespace_spec.rb +++ b/spec/models/namespace_spec.rb @@ -2356,7 +2356,7 @@ RSpec.describe Namespace do end end - describe 'storage_enforcement_date' do + describe 'storage_enforcement_date', :freeze_time do let_it_be(:namespace) { create(:group) } before do @@ -2364,7 +2364,7 @@ RSpec.describe Namespace do end it 'returns correct date' do - expect(namespace.storage_enforcement_date).to eql(Date.new(2022, 10, 19)) + expect(namespace.storage_enforcement_date).to eql(3.months.from_now.to_date) end context 'when :storage_banner_bypass_date_check is enabled' do @@ -2372,7 +2372,7 @@ RSpec.describe Namespace do stub_feature_flags(namespace_storage_limit_bypass_date_check: true) end - it 'returns the current date', :freeze_time do + it 'returns the current date' do expect(namespace.storage_enforcement_date).to eq(Date.current) end end diff --git a/spec/models/personal_access_token_spec.rb b/spec/models/personal_access_token_spec.rb index 67e7d444d25..73ec51ea801 100644 --- a/spec/models/personal_access_token_spec.rb +++ b/spec/models/personal_access_token_spec.rb @@ -194,47 +194,6 @@ RSpec.describe PersonalAccessToken do end end - describe 'Redis storage' do - let(:user_id) { 123 } - let(:token) { 'KS3wegQYXBLYhQsciwsj' } - - context 'reading encrypted data' do - before do - subject.redis_store!(user_id, token) - end - - it 'returns stored data' do - expect(subject.redis_getdel(user_id)).to eq(token) - end - end - - context 'reading unencrypted data' do - before do - Gitlab::Redis::SharedState.with do |redis| - redis.set(described_class.redis_shared_state_key(user_id), - token, - ex: PersonalAccessToken::REDIS_EXPIRY_TIME) - end - end - - it 'returns stored data unmodified' do - expect(subject.redis_getdel(user_id)).to eq(token) - end - end - - context 'after deletion' do - before do - subject.redis_store!(user_id, token) - - expect(subject.redis_getdel(user_id)).to eq(token) - end - - it 'token is removed' do - expect(subject.redis_getdel(user_id)).to be_nil - end - end - end - context "validations" do let(:personal_access_token) { build(:personal_access_token) } @@ -365,7 +324,7 @@ RSpec.describe PersonalAccessToken do describe '.simple_sorts' do it 'includes overridden keys' do - expect(described_class.simple_sorts.keys).to include(*%w(expires_at_asc expires_at_desc expires_at_asc_id_desc)) + expect(described_class.simple_sorts.keys).to include(*%w(expires_at_asc_id_desc)) end end @@ -373,18 +332,6 @@ RSpec.describe PersonalAccessToken do let_it_be(:earlier_token) { create(:personal_access_token, expires_at: 2.days.ago) } let_it_be(:later_token) { create(:personal_access_token, expires_at: 1.day.ago) } - describe '.order_expires_at_asc' do - it 'returns ordered list in asc order of expiry date' do - expect(described_class.order_expires_at_asc).to match [earlier_token, later_token] - end - end - - describe '.order_expires_at_desc' do - it 'returns ordered list in desc order of expiry date' do - expect(described_class.order_expires_at_desc).to match [later_token, earlier_token] - end - end - describe '.order_expires_at_asc_id_desc' do let_it_be(:earlier_token_2) { create(:personal_access_token, expires_at: 2.days.ago) } diff --git a/spec/presenters/ci/build_runner_presenter_spec.rb b/spec/presenters/ci/build_runner_presenter_spec.rb index 396fe7843ba..8d6278ab1d7 100644 --- a/spec/presenters/ci/build_runner_presenter_spec.rb +++ b/spec/presenters/ci/build_runner_presenter_spec.rb @@ -353,7 +353,8 @@ RSpec.describe Ci::BuildRunnerPresenter do it 'logs file_variable_is_referenced_in_another_variable' do expect(Gitlab::AppJsonLogger).to receive(:info).with( event: 'file_variable_is_referenced_in_another_variable', - project_id: project.id + project_id: project.id, + variable: 'file_var' ).once runner_variables diff --git a/spec/requests/api/integrations/jira_connect/subscriptions_spec.rb b/spec/requests/api/integrations/jira_connect/subscriptions_spec.rb index 8a222a99b34..6b26eaad2f3 100644 --- a/spec/requests/api/integrations/jira_connect/subscriptions_spec.rb +++ b/spec/requests/api/integrations/jira_connect/subscriptions_spec.rb @@ -22,7 +22,7 @@ RSpec.describe API::Integrations::JiraConnect::Subscriptions do context 'with feature flag disabled' do before do - stub_feature_flags(jira_connect_oauth: false) + stub_feature_flags(jira_connect_oauth_self_managed: false) end let(:jwt) { '123' } diff --git a/spec/requests/jira_connect/subscriptions_controller_spec.rb b/spec/requests/jira_connect/subscriptions_controller_spec.rb index f407ea09250..ee5c26295fd 100644 --- a/spec/requests/jira_connect/subscriptions_controller_spec.rb +++ b/spec/requests/jira_connect/subscriptions_controller_spec.rb @@ -28,9 +28,9 @@ RSpec.describe JiraConnect::SubscriptionsController do it { is_expected.not_to include('http://self-managed-gitlab.com/api/') } end - context 'with jira_connect_oauth_self_managed feature disabled' do + context 'with jira_connect_oauth_self_managed_setting feature disabled' do before do - stub_feature_flags(jira_connect_oauth_self_managed: false) + stub_feature_flags(jira_connect_oauth_self_managed_setting: false) end it { is_expected.not_to include('http://self-managed-gitlab.com/-/jira_connect/') } diff --git a/spec/support/rspec_order_todo.yml b/spec/support/rspec_order_todo.yml index 0558bfd51c3..b8fe8412d55 100644 --- a/spec/support/rspec_order_todo.yml +++ b/spec/support/rspec_order_todo.yml @@ -3379,7 +3379,6 @@ - './ee/spec/views/registrations/welcome/continuous_onboarding_getting_started.html.haml_spec.rb' - './ee/spec/views/registrations/welcome/show.html.haml_spec.rb' - './ee/spec/views/search/_category.html.haml_spec.rb' -- './ee/spec/views/shared/access_tokens/_table.html.haml_spec.rb' - './ee/spec/views/shared/billings/_billing_plan_actions.html.haml_spec.rb' - './ee/spec/views/shared/billings/_billing_plan.html.haml_spec.rb' - './ee/spec/views/shared/billings/_billing_plans.html.haml_spec.rb' @@ -10767,7 +10766,6 @@ - './spec/views/registrations/welcome/show.html.haml_spec.rb' - './spec/views/search/_results.html.haml_spec.rb' - './spec/views/search/show.html.haml_spec.rb' -- './spec/views/shared/access_tokens/_table.html.haml_spec.rb' - './spec/views/shared/deploy_tokens/_form.html.haml_spec.rb' - './spec/views/shared/groups/_dropdown.html.haml_spec.rb' - './spec/views/shared/issuable/_sidebar.html.haml_spec.rb' diff --git a/spec/tasks/gitlab/gitaly_rake_spec.rb b/spec/tasks/gitlab/gitaly_rake_spec.rb index e57021f749b..d2f4fa0b8ef 100644 --- a/spec/tasks/gitlab/gitaly_rake_spec.rb +++ b/spec/tasks/gitlab/gitaly_rake_spec.rb @@ -66,7 +66,7 @@ RSpec.describe 'gitlab:gitaly namespace rake task', :silence_stdout do .with(%w[which gmake]) .and_return(['/usr/bin/gmake', 0]) expect(Gitlab::Popen).to receive(:popen) - .with(%w[gmake clean-build all git], nil, { "BUNDLE_GEMFILE" => nil, "RUBYOPT" => nil }) + .with(%w[gmake clean-build all], nil, { "BUNDLE_GEMFILE" => nil, "RUBYOPT" => nil }) .and_return(['ok', 0]) subject @@ -78,7 +78,7 @@ RSpec.describe 'gitlab:gitaly namespace rake task', :silence_stdout do .with(%w[which gmake]) .and_return(['/usr/bin/gmake', 0]) expect(Gitlab::Popen).to receive(:popen) - .with(%w[gmake clean-build all git], nil, { "BUNDLE_GEMFILE" => nil, "RUBYOPT" => nil }) + .with(%w[gmake clean-build all], nil, { "BUNDLE_GEMFILE" => nil, "RUBYOPT" => nil }) .and_return(['output', 1]) expect { subject }.to raise_error /Gitaly failed to compile: output/ @@ -95,14 +95,14 @@ RSpec.describe 'gitlab:gitaly namespace rake task', :silence_stdout do it 'calls make in the gitaly directory' do expect(Gitlab::Popen).to receive(:popen) - .with(%w[make clean-build all git], nil, { "BUNDLE_GEMFILE" => nil, "RUBYOPT" => nil }) + .with(%w[make clean-build all], nil, { "BUNDLE_GEMFILE" => nil, "RUBYOPT" => nil }) .and_return(['output', 0]) subject end context 'when Rails.env is test' do - let(:command) { %w[make clean-build all git] } + let(:command) { %w[make clean-build all] } before do stub_rails_env('test') diff --git a/spec/views/admin/application_settings/general.html.haml_spec.rb b/spec/views/admin/application_settings/general.html.haml_spec.rb index c7d156cde39..a9c470e49df 100644 --- a/spec/views/admin/application_settings/general.html.haml_spec.rb +++ b/spec/views/admin/application_settings/general.html.haml_spec.rb @@ -76,9 +76,9 @@ RSpec.describe 'admin/application_settings/general.html.haml' do expect(rendered).to have_css('#js-jira_connect-settings') end - context 'when the jira_connect_oauth feature flag is disabled' do + context 'when the jira_connect_oauth_self_managed_setting feature flag is disabled' do before do - stub_feature_flags(jira_connect_oauth: false) + stub_feature_flags(jira_connect_oauth_self_managed_setting: false) end it 'does not show the jira connect application key section' do diff --git a/spec/views/shared/access_tokens/_table.html.haml_spec.rb b/spec/views/shared/access_tokens/_table.html.haml_spec.rb deleted file mode 100644 index 74de9e12d04..00000000000 --- a/spec/views/shared/access_tokens/_table.html.haml_spec.rb +++ /dev/null @@ -1,151 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe 'shared/access_tokens/_table.html.haml' do - let(:type) { 'token' } - let(:type_plural) { 'tokens' } - let(:empty_message) { nil } - let(:impersonation) { false } - - let_it_be(:user) { create(:user) } - let_it_be(:tokens) { [create(:personal_access_token, user: user)] } - let_it_be(:resource) { false } - - before do - if resource - resource.add_maintainer(user) - end - - # Forcibly removing scopes from one token as it's not possible to do with the current modal on creation - # But the check exists in the template (it may be there for legacy reasons), so we should test the outcome - if tokens.size > 1 - tokens[1].scopes = [] - end - - locals = { - type: type, - type_plural: type_plural, - active_tokens: tokens, - resource: resource, - impersonation: impersonation, - revoke_route_helper: ->(token) { 'path/' } - } - - if empty_message - locals[:no_active_tokens_message] = empty_message - end - - render partial: 'shared/access_tokens/table', locals: locals - end - - context 'if personal' do - it 'does not show non-personal content', :aggregate_failures do - expect(rendered).not_to have_content 'To see all the user\'s personal access tokens you must impersonate them first.' - expect(rendered).not_to have_selector 'th', text: 'Role' - end - end - - context 'if impersonation' do - let(:impersonation) { true } - - it 'shows the impersonation content', :aggregate_failures do - expect(rendered).to have_content 'To see all the user\'s personal access tokens you must impersonate them first.' - - expect(rendered).not_to have_content 'Personal access tokens are not revoked upon expiration.' - expect(rendered).not_to have_selector 'th', text: 'Role' - end - end - - context 'if resource is project' do - let_it_be(:resource) { create(:project) } - - it 'shows the project content', :aggregate_failures do - expect(rendered).to have_selector 'th', text: 'Role' - expect(rendered).to have_selector 'td', text: 'Maintainer' - - expect(rendered).not_to have_content 'Personal access tokens are not revoked upon expiration.' - expect(rendered).not_to have_content 'To see all the user\'s personal access tokens you must impersonate them first.' - end - end - - context 'if resource is group' do - let_it_be(:resource) { create(:group) } - - it 'shows the group content', :aggregate_failures do - expect(rendered).to have_selector 'th', text: 'Role' - expect(rendered).to have_selector 'td', text: 'Maintainer' - - expect(rendered).not_to have_content 'Personal access tokens are not revoked upon expiration.' - expect(rendered).not_to have_content 'To see all the user\'s personal access tokens you must impersonate them first.' - end - end - - context 'without tokens' do - let_it_be(:tokens) { [] } - - it 'has the correct content', :aggregate_failures do - expect(rendered).to have_content 'Active tokens (0)' - expect(rendered).to have_content 'This user has no active tokens.' - end - - context 'with a custom empty text' do - let(:empty_message) { 'Custom empty message' } - - it 'shows the custom empty text' do - expect(rendered).to have_content empty_message - end - end - end - - context 'with tokens' do - let_it_be(:tokens) do - [ - create(:personal_access_token, user: user, name: 'Access token', last_used_at: 4.days.from_now, expires_at: nil, scopes: [:read_api, :read_user]), - create(:personal_access_token, user: user, expires_at: 1.day.from_now, scopes: [:read_api, :read_user]) - ] - end - - let_it_be(:expired_token) { build(:personal_access_token, name: "Expired token", expires_at: 2.days.ago).tap { |t| t.save!(validate: false) } } - - it 'has the correct content', :aggregate_failures do - # Heading content - expect(rendered).to have_content 'Active tokens (2)' - - # Table headers - expect(rendered).to have_selector 'th', text: 'Token name' - expect(rendered).to have_selector 'th', text: 'Scopes' - expect(rendered).to have_selector 'th', text: 'Created' - expect(rendered).to have_selector 'th', text: 'Last Used' - expect(rendered).to have_selector 'th', text: 'Expires' - - # Table contents - expect(rendered).to have_content 'Access token' - expect(rendered).not_to have_content 'Expired token' - expect(rendered).to have_content 'read_api, read_user' - expect(rendered).to have_content 'no scopes selected' - expect(rendered).to have_content Time.now.to_date.to_s(:medium) - expect(rendered).to have_content l(4.days.from_now, format: "%b %d, %Y") - - # Revoke buttons - expect(rendered).to have_link 'Revoke', href: 'path/', class: 'btn-danger-secondary', count: 1 - expect(rendered).to have_link 'Revoke', href: 'path/', count: 2 - end - - context 'without the last used time' do - let_it_be(:tokens) { [create(:personal_access_token, user: user, expires_at: 5.days.ago)] } - - it 'shows the last used empty text' do - expect(rendered).to have_content 'Never' - end - end - - context 'without expired at' do - let_it_be(:tokens) { [create(:personal_access_token, user: user, expires_at: nil, last_used_at: 1.day.ago)] } - - it 'shows the expired at empty text' do - expect(rendered).to have_content 'Never' - end - end - end -end |